@@ -1586,21 +1586,62 @@ pub fn unlinkat(dirfd: i32, path: [*:0]const u8, flags: u32) usize {
1586
1586
return syscall3 (.unlinkat , @as (usize , @bitCast (@as (isize , dirfd ))), @intFromPtr (path ), flags );
1587
1587
}
1588
1588
1589
- pub fn waitpid (pid : pid_t , status : * u32 , flags : u32 ) usize {
1590
- return syscall4 ( . wait4, @as ( usize , @bitCast ( @as ( isize , pid ))), @intFromPtr ( status ) , flags , 0 );
1589
+ pub fn waitpid (pid : pid_t , status : ? * u32 , flags : u32 ) usize {
1590
+ return wait4 ( pid , status , flags , null );
1591
1591
}
1592
1592
1593
- pub fn wait4 (pid : pid_t , status : * u32 , flags : u32 , usage : ? * rusage ) usize {
1594
- return syscall4 (
1595
- .wait4 ,
1596
- @as (usize , @bitCast (@as (isize , pid ))),
1597
- @intFromPtr (status ),
1598
- flags ,
1593
+ pub fn wait4 (pid : pid_t , status : ? * u32 , flags : u32 , usage : ? * rusage ) usize {
1594
+ if (@hasField (SYS , "wait4" )) {
1595
+ return syscall4 (
1596
+ .wait4 ,
1597
+ @as (usize , @bitCast (@as (isize , pid ))),
1598
+ @intFromPtr (status ),
1599
+ flags ,
1600
+ @intFromPtr (usage ),
1601
+ );
1602
+ }
1603
+
1604
+ // Emulate wait4 using waitid; adapted from musl/src/internal/emulate_wait4.c
1605
+
1606
+ const id_type : P = if (pid < -1 or pid == 0 ) .PGID else if (pid == -1 ) .ALL else .PID ;
1607
+ const id = if (pid < -1 ) - pid else pid ;
1608
+
1609
+ var info : siginfo_t = undefined ;
1610
+ info .fields .common .first .piduid .pid = 0 ;
1611
+
1612
+ const r = syscall5 (
1613
+ .waitid ,
1614
+ @intFromEnum (id_type ),
1615
+ @bitCast (@as (isize , id )),
1616
+ @intFromPtr (& info ),
1617
+ flags | W .EXITED ,
1599
1618
@intFromPtr (usage ),
1600
1619
);
1620
+ if (@clz (r ) == 0 ) return r ; // r < 0
1621
+ // WNOHANG passed and no children in waitable state
1622
+ if (info .fields .common .first .piduid .pid == 0 ) return 0 ;
1623
+
1624
+ if (status ) | s | {
1625
+ const si_status : u32 = @bitCast (info .fields .common .second .sigchld .status );
1626
+ s .* = switch (info .code ) {
1627
+ // CLD_EXITED
1628
+ 1 = > (si_status & 0xff ) << 8 ,
1629
+ // CLD_KILLED
1630
+ 2 = > si_status & 0x7f ,
1631
+ // CLD_DUMPED
1632
+ 3 = > si_status & 0x7f | 0x80 ,
1633
+ // CLD_TRAPPED, CLD_STOPPED
1634
+ // see ptrace(2); the high bits of si_status can contain PTRACE_EVENT_ values which must be preserved
1635
+ 4 , 5 = > (si_status << 8 ) + 0x7f ,
1636
+ // CLD_CONTINUED
1637
+ 6 = > 0xffff ,
1638
+ else = > unreachable ,
1639
+ };
1640
+ }
1641
+ return @bitCast (@as (isize , info .fields .common .first .piduid .pid ));
1601
1642
}
1602
1643
1603
- pub fn waitid (id_type : P , id : i32 , infop : * siginfo_t , flags : u32 ) usize {
1644
+ pub fn waitid (id_type : P , id : pid_t , infop : * siginfo_t , flags : u32 ) usize {
1604
1645
return syscall5 (.waitid , @intFromEnum (id_type ), @as (usize , @bitCast (@as (isize , id ))), @intFromPtr (infop ), flags , 0 );
1605
1646
}
1606
1647
0 commit comments