@@ -163,7 +163,7 @@ impl FileDescription for AnonSocket {
163163 } else {
164164 // Blocking socketpair with writer and empty buffer.
165165 // FIXME: blocking is currently not supported
166- throw_unsup_format ! ( "socketpair read: blocking isn't supported yet" ) ;
166+ throw_unsup_format ! ( "socketpair/pipe/pipe2 read: blocking isn't supported yet" ) ;
167167 }
168168 }
169169 }
@@ -230,7 +230,7 @@ impl FileDescription for AnonSocket {
230230 return ecx. set_last_error_and_return ( ErrorKind :: WouldBlock , dest) ;
231231 } else {
232232 // Blocking socketpair with a full buffer.
233- throw_unsup_format ! ( "socketpair write: blocking isn't supported yet" ) ;
233+ throw_unsup_format ! ( "socketpair/pipe/pipe2 write: blocking isn't supported yet" ) ;
234234 }
235235 }
236236 // Remember this clock so `read` can synchronize with us.
@@ -267,21 +267,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
267267 let this = self . eval_context_mut ( ) ;
268268
269269 let domain = this. read_scalar ( domain) ?. to_i32 ( ) ?;
270- let mut type_ = this. read_scalar ( type_) ?. to_i32 ( ) ?;
270+ let mut flags = this. read_scalar ( type_) ?. to_i32 ( ) ?;
271271 let protocol = this. read_scalar ( protocol) ?. to_i32 ( ) ?;
272272 let sv = this. deref_pointer ( sv) ?;
273273
274274 let mut is_sock_nonblock = false ;
275275
276- // Parse and remove the type flags that we support.
277- // SOCK_NONBLOCK only exists on Linux .
276+ // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so
277+ // if there is anything left at the end, that's an unsupported flag .
278278 if this. tcx . sess . target . os == "linux" {
279- if type_ & this. eval_libc_i32 ( "SOCK_NONBLOCK" ) == this. eval_libc_i32 ( "SOCK_NONBLOCK" ) {
279+ // SOCK_NONBLOCK only exists on Linux.
280+ let sock_nonblock = this. eval_libc_i32 ( "SOCK_NONBLOCK" ) ;
281+ let sock_cloexec = this. eval_libc_i32 ( "SOCK_CLOEXEC" ) ;
282+ if flags & sock_nonblock == sock_nonblock {
280283 is_sock_nonblock = true ;
281- type_ &= !( this . eval_libc_i32 ( "SOCK_NONBLOCK" ) ) ;
284+ flags &= !sock_nonblock ;
282285 }
283- if type_ & this . eval_libc_i32 ( "SOCK_CLOEXEC" ) == this . eval_libc_i32 ( "SOCK_CLOEXEC" ) {
284- type_ &= !( this . eval_libc_i32 ( "SOCK_CLOEXEC" ) ) ;
286+ if flags & sock_cloexec == sock_cloexec {
287+ flags &= !sock_cloexec ;
285288 }
286289 }
287290
@@ -294,11 +297,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
294297 and AF_LOCAL are allowed",
295298 domain
296299 ) ;
297- } else if type_ != this. eval_libc_i32 ( "SOCK_STREAM" ) {
300+ } else if flags != this. eval_libc_i32 ( "SOCK_STREAM" ) {
298301 throw_unsup_format ! (
299302 "socketpair: type {:#x} is unsupported, only SOCK_STREAM, \
300303 SOCK_CLOEXEC and SOCK_NONBLOCK are allowed",
301- type_
304+ flags
302305 ) ;
303306 } else if protocol != 0 {
304307 throw_unsup_format ! (
@@ -347,14 +350,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
347350 let this = self . eval_context_mut ( ) ;
348351
349352 let pipefd = this. deref_pointer_as ( pipefd, this. machine . layouts . i32 ) ?;
350- let flags = match flags {
353+ let mut flags = match flags {
351354 Some ( flags) => this. read_scalar ( flags) ?. to_i32 ( ) ?,
352355 None => 0 ,
353356 } ;
354357
355- // As usual we ignore CLOEXEC.
356358 let cloexec = this. eval_libc_i32 ( "O_CLOEXEC" ) ;
357- if flags != 0 && flags != cloexec {
359+ let o_nonblock = this. eval_libc_i32 ( "O_NONBLOCK" ) ;
360+
361+ // Interpret the flag. Every flag we recognize is "subtracted" from `flags`, so
362+ // if there is anything left at the end, that's an unsupported flag.
363+ let mut is_nonblock = false ;
364+ if flags & o_nonblock == o_nonblock {
365+ is_nonblock = true ;
366+ flags &= !o_nonblock;
367+ }
368+ // As usual we ignore CLOEXEC.
369+ if flags & cloexec == cloexec {
370+ flags &= !cloexec;
371+ }
372+ if flags != 0 {
358373 throw_unsup_format ! ( "unsupported flags in `pipe2`" ) ;
359374 }
360375
@@ -365,13 +380,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
365380 readbuf : Some ( RefCell :: new ( Buffer :: new ( ) ) ) ,
366381 peer_fd : OnceCell :: new ( ) ,
367382 peer_lost_data : Cell :: new ( false ) ,
368- is_nonblock : false ,
383+ is_nonblock,
369384 } ) ;
370385 let fd1 = fds. new_ref ( AnonSocket {
371386 readbuf : None ,
372387 peer_fd : OnceCell :: new ( ) ,
373388 peer_lost_data : Cell :: new ( false ) ,
374- is_nonblock : false ,
389+ is_nonblock,
375390 } ) ;
376391
377392 // Make the file descriptions point to each other.
0 commit comments