@@ -270,7 +270,7 @@ pub fn errno(rc: anytype) E {
270
270
if (use_libc ) {
271
271
return if (rc == -1 ) @enumFromInt (std .c ._errno ().* ) else .SUCCESS ;
272
272
}
273
- const signed : isize = @ bitCast (rc );
273
+ const signed : isize = if ( @typeInfo ( @TypeOf ( rc )). int . signedness == .unsigned ) @ bitCast (@as ( usize , rc )) else rc ;
274
274
const int = if (signed > -4096 and signed < 0 ) - signed else 0 ;
275
275
return @enumFromInt (int );
276
276
}
@@ -4420,7 +4420,9 @@ pub const WaitPidResult = struct {
4420
4420
/// Use this version of the `waitpid` wrapper if you spawned your child process using explicit
4421
4421
/// `fork` and `execve` method.
4422
4422
pub fn waitpid (pid : pid_t , flags : u32 ) WaitPidResult {
4423
- var status : if (builtin .link_libc ) c_int else u32 = undefined ;
4423
+ if (! use_libc and builtin .os .tag == .linux ) return wait4 (pid , flags , null );
4424
+
4425
+ var status : if (use_libc ) c_int else u32 = undefined ;
4424
4426
while (true ) {
4425
4427
const rc = system .waitpid (pid , & status , @intCast (flags ));
4426
4428
switch (errno (rc )) {
@@ -4437,12 +4439,11 @@ pub fn waitpid(pid: pid_t, flags: u32) WaitPidResult {
4437
4439
}
4438
4440
4439
4441
pub fn wait4 (pid : pid_t , flags : u32 , ru : ? * rusage ) WaitPidResult {
4440
- var status : if (builtin .link_libc ) c_int else u32 = undefined ;
4441
4442
while (true ) {
4442
- const rc = system . wait4 (pid , & status , @intCast ( flags ) , ru );
4443
+ const rc , const status = wait4_impl (pid , flags , ru );
4443
4444
switch (errno (rc )) {
4444
4445
.SUCCESS = > return .{
4445
- .pid = @intCast ( rc ) ,
4446
+ .pid = rc ,
4446
4447
.status = @bitCast (status ),
4447
4448
},
4448
4449
.INTR = > continue ,
@@ -4453,6 +4454,44 @@ pub fn wait4(pid: pid_t, flags: u32, ru: ?*rusage) WaitPidResult {
4453
4454
}
4454
4455
}
4455
4456
4457
+ fn wait4_impl (pid : pid_t , flags : u32 , ru : ? * rusage ) struct { pid_t , if (use_libc ) c_int else u32 } {
4458
+ if (use_libc or builtin .os .tag != .linux ) {
4459
+ var status : if (use_libc ) c_int else u32 = undefined ;
4460
+ const rc = system .wait4 (pid , & status , @intCast (flags ), ru );
4461
+ return .{ rc , status };
4462
+ }
4463
+
4464
+ // Emulate wait4 using waitid; adapted from musl/src/internal/emulate_wait4.c
4465
+
4466
+ const id_type : system.P = if (pid < -1 or pid == 0 ) .PGID else if (pid == -1 ) .ALL else .PID ;
4467
+ const id = if (pid < -1 ) - pid else pid ;
4468
+
4469
+ var info : siginfo_t = undefined ;
4470
+ info .fields .common .first .piduid .pid = 0 ;
4471
+
4472
+ const r : isize = @bitCast (system .waitid (id_type , id , & info , flags | W .EXITED , ru ));
4473
+ if (r < 0 ) return .{ @intCast (r ), 0 }; // r < 0
4474
+ // WNOHANG passed and no children in waitable state
4475
+ if (info .fields .common .first .piduid .pid == 0 ) return .{ 0 , 0 };
4476
+
4477
+ const si_status : u32 = @bitCast (info .fields .common .second .sigchld .status );
4478
+ const status = switch (info .code ) {
4479
+ // CLD_EXITED
4480
+ 1 = > (si_status & 0xff ) << 8 ,
4481
+ // CLD_KILLED
4482
+ 2 = > si_status & 0x7f ,
4483
+ // CLD_DUMPED
4484
+ 3 = > si_status & 0x7f | 0x80 ,
4485
+ // CLD_TRAPPED, CLD_STOPPED
4486
+ // see ptrace(2); the high bits of si_status can contain PTRACE_EVENT_ values which must be preserved
4487
+ 4 , 5 = > (si_status << 8 ) + 0x7f ,
4488
+ // CLD_CONTINUED
4489
+ 6 = > 0xffff ,
4490
+ else = > unreachable ,
4491
+ };
4492
+ return .{ info .fields .common .first .piduid .pid , status };
4493
+ }
4494
+
4456
4495
pub const FStatError = error {
4457
4496
SystemResources ,
4458
4497
0 commit comments