@@ -7,8 +7,6 @@ use std::collections::VecDeque;
7
7
use std:: io;
8
8
use std:: io:: ErrorKind ;
9
9
10
- use rustc_abi:: Size ;
11
-
12
10
use crate :: concurrency:: VClock ;
13
11
use crate :: shims:: files:: {
14
12
EvalContextExt as _, FileDescription , FileDescriptionRef , WeakFileDescriptionRef ,
@@ -103,10 +101,10 @@ impl FileDescription for AnonSocket {
103
101
_communicate_allowed : bool ,
104
102
ptr : Pointer ,
105
103
len : usize ,
106
- dest : & MPlaceTy < ' tcx > ,
107
104
ecx : & mut MiriInterpCx < ' tcx > ,
105
+ finish : DynMachineCallback < ' tcx , Result < usize , IoError > > ,
108
106
) -> InterpResult < ' tcx > {
109
- anonsocket_write ( self , ptr, len, dest , ecx )
107
+ anonsocket_write ( self , ptr, len, ecx , finish )
110
108
}
111
109
112
110
fn as_unix ( & self ) -> & dyn UnixFileDescription {
@@ -119,39 +117,38 @@ fn anonsocket_write<'tcx>(
119
117
self_ref : FileDescriptionRef < AnonSocket > ,
120
118
ptr : Pointer ,
121
119
len : usize ,
122
- dest : & MPlaceTy < ' tcx > ,
123
120
ecx : & mut MiriInterpCx < ' tcx > ,
121
+ finish : DynMachineCallback < ' tcx , Result < usize , IoError > > ,
124
122
) -> InterpResult < ' tcx > {
125
123
// Always succeed on write size 0.
126
124
// ("If count is zero and fd refers to a file other than a regular file, the results are not specified.")
127
125
if len == 0 {
128
- return ecx . return_write_success ( 0 , dest ) ;
126
+ return finish . call ( ecx , Ok ( 0 ) ) ;
129
127
}
130
128
131
129
// We are writing to our peer's readbuf.
132
130
let Some ( peer_fd) = self_ref. peer_fd ( ) . upgrade ( ) else {
133
131
// If the upgrade from Weak to Rc fails, it indicates that all read ends have been
134
132
// closed. It is an error to write even if there would be space.
135
- return ecx . set_last_error_and_return ( ErrorKind :: BrokenPipe , dest ) ;
133
+ return finish . call ( ecx , Err ( ErrorKind :: BrokenPipe . into ( ) ) ) ;
136
134
} ;
137
135
138
136
let Some ( writebuf) = & peer_fd. readbuf else {
139
137
// Writing to the read end of a pipe.
140
- return ecx . set_last_error_and_return ( IoError :: LibcError ( "EBADF" ) , dest ) ;
138
+ return finish . call ( ecx , Err ( IoError :: LibcError ( "EBADF" ) ) ) ;
141
139
} ;
142
140
143
141
// Let's see if we can write.
144
142
let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY . strict_sub ( writebuf. borrow ( ) . buf . len ( ) ) ;
145
143
if available_space == 0 {
146
144
if self_ref. is_nonblock {
147
145
// Non-blocking socketpair with a full buffer.
148
- return ecx . set_last_error_and_return ( ErrorKind :: WouldBlock , dest ) ;
146
+ return finish . call ( ecx , Err ( ErrorKind :: WouldBlock . into ( ) ) ) ;
149
147
} else {
150
148
self_ref. blocked_write_tid . borrow_mut ( ) . push ( ecx. active_thread ( ) ) ;
151
149
// Blocking socketpair with a full buffer.
152
150
// Block the current thread; only keep a weak ref for this.
153
151
let weak_self_ref = FileDescriptionRef :: downgrade ( & self_ref) ;
154
- let dest = dest. clone ( ) ;
155
152
ecx. block_thread (
156
153
BlockReason :: UnnamedSocket ,
157
154
None ,
@@ -160,14 +157,14 @@ fn anonsocket_write<'tcx>(
160
157
weak_self_ref: WeakFileDescriptionRef <AnonSocket >,
161
158
ptr: Pointer ,
162
159
len: usize ,
163
- dest : MPlaceTy <' tcx>,
160
+ finish : DynMachineCallback <' tcx, Result < usize , IoError > >,
164
161
}
165
162
|this, unblock: UnblockKind | {
166
163
assert_eq!( unblock, UnblockKind :: Ready ) ;
167
164
// If we got unblocked, then our peer successfully upgraded its weak
168
165
// ref to us. That means we can also upgrade our weak ref.
169
166
let self_ref = weak_self_ref. upgrade( ) . unwrap( ) ;
170
- anonsocket_write( self_ref, ptr, len, & dest , this )
167
+ anonsocket_write( self_ref, ptr, len, this , finish )
171
168
}
172
169
) ,
173
170
) ;
@@ -180,9 +177,9 @@ fn anonsocket_write<'tcx>(
180
177
writebuf. clock . join ( clock) ;
181
178
} ) ;
182
179
// Do full write / partial write based on the space available.
183
- let actual_write_size = len. min ( available_space) ;
184
- let bytes = ecx. read_bytes_ptr_strip_provenance ( ptr , Size :: from_bytes ( len ) ) ? ;
185
- writebuf . buf . extend ( & bytes [ .. actual_write_size] ) ;
180
+ let write_size = len. min ( available_space) ;
181
+ let actual_write_size = ecx. write_to_host ( & mut writebuf . buf , write_size , ptr ) ? . unwrap ( ) ;
182
+ assert_eq ! ( actual_write_size, write_size ) ;
186
183
187
184
// Need to stop accessing peer_fd so that it can be notified.
188
185
drop ( writebuf) ;
@@ -197,7 +194,7 @@ fn anonsocket_write<'tcx>(
197
194
// The kernel does this even if the fd was already readable before, so we follow suit.
198
195
ecx. check_and_update_readiness ( peer_fd) ?;
199
196
200
- return ecx . return_write_success ( actual_write_size , dest ) ;
197
+ return finish . call ( ecx , Ok ( write_size ) ) ;
201
198
}
202
199
interp_ok ( ( ) )
203
200
}
0 commit comments