@@ -1114,6 +1114,23 @@ pub const IO_Uring = struct {
11141114 return sqe ;
11151115 }
11161116
1117+ /// Queues (but does not submit) an SQE to perform a `waitid(2)`.
1118+ /// Returns a pointer to the SQE.
1119+ pub fn waitid (
1120+ self : * IO_Uring ,
1121+ user_data : u64 ,
1122+ id_type : linux.P ,
1123+ id : i32 ,
1124+ infop : * linux.siginfo_t ,
1125+ options : u32 ,
1126+ flags : u32 ,
1127+ ) ! * linux.io_uring_sqe {
1128+ const sqe = try self .get_sqe ();
1129+ io_uring_prep_waitid (sqe , id_type , id , infop , options , flags );
1130+ sqe .user_data = user_data ;
1131+ return sqe ;
1132+ }
1133+
11171134 /// Registers an array of file descriptors.
11181135 /// Every time a file descriptor is put in an SQE and submitted to the kernel, the kernel must
11191136 /// retrieve a reference to the file, and once I/O has completed the file reference must be
@@ -1962,6 +1979,19 @@ pub fn io_uring_prep_socket_direct_alloc(
19621979 __io_uring_set_target_fixed_file (sqe , linux .IORING_FILE_INDEX_ALLOC );
19631980}
19641981
1982+ pub fn io_uring_prep_waitid (
1983+ sqe : * linux.io_uring_sqe ,
1984+ id_type : linux.P ,
1985+ id : i32 ,
1986+ infop : * linux.siginfo_t ,
1987+ options : u32 ,
1988+ flags : u32 ,
1989+ ) void {
1990+ io_uring_prep_rw (.WAITID , sqe , id , 0 , @intFromEnum (id_type ), @intFromPtr (infop ));
1991+ sqe .rw_flags = flags ;
1992+ sqe .splice_fd_in = @bitCast (options );
1993+ }
1994+
19651995test "structs/offsets/entries" {
19661996 if (builtin .os .tag != .linux ) return error .SkipZigTest ;
19671997
@@ -4148,6 +4178,32 @@ test "openat_direct/close_direct" {
41484178 try ring .unregister_files ();
41494179}
41504180
4181+ test "waitid" {
4182+ try skipKernelLessThan (.{ .major = 6 , .minor = 7 , .patch = 0 });
4183+
4184+ var ring = IO_Uring .init (16 , 0 ) catch | err | switch (err ) {
4185+ error .SystemOutdated = > return error .SkipZigTest ,
4186+ error .PermissionDenied = > return error .SkipZigTest ,
4187+ else = > return err ,
4188+ };
4189+ defer ring .deinit ();
4190+
4191+ const pid = try os .fork ();
4192+ if (pid == 0 ) {
4193+ os .exit (7 );
4194+ }
4195+
4196+ var siginfo : os.siginfo_t = undefined ;
4197+ _ = try ring .waitid (0 , .PID , pid , & siginfo , os .W .EXITED , 0 );
4198+
4199+ try testing .expectEqual (1 , try ring .submit ());
4200+
4201+ const cqe_waitid = try ring .copy_cqe ();
4202+ try testing .expectEqual (0 , cqe_waitid .res );
4203+ try testing .expectEqual (pid , siginfo .fields .common .first .piduid .pid );
4204+ try testing .expectEqual (7 , siginfo .fields .common .second .sigchld .status );
4205+ }
4206+
41514207/// For use in tests. Returns SkipZigTest is kernel version is less than required.
41524208inline fn skipKernelLessThan (required : std.SemanticVersion ) ! void {
41534209 if (builtin .os .tag != .linux ) return error .SkipZigTest ;
0 commit comments