@@ -859,34 +859,85 @@ test "shutdown socket" {
859859 std .net .Stream .close (.{ .handle = sock });
860860}
861861
862- test "sigaction" {
862+ test "sigset empty/full" {
863+ if (native_os == .wasi or native_os == .windows )
864+ return error .SkipZigTest ;
865+
866+ var set : posix.sigset_t = undefined ;
867+
868+ posix .sigemptyset (& set );
869+ for (1.. posix .NSIG ) | i | {
870+ try expectEqual (false , posix .sigismember (& set , @truncate (i )));
871+ }
872+
873+ // The C library can reserve some (unnamed) signals, so can't check the full
874+ // NSIG set is defined, but just test a couple:
875+ posix .sigfillset (& set );
876+ try expectEqual (true , posix .sigismember (& set , @truncate (posix .SIG .USR1 )));
877+ try expectEqual (true , posix .sigismember (& set , @truncate (posix .SIG .INT )));
878+ }
879+
880+ // Some signals (32 - 34 on glibc/musl) are not allowed to be added to a
881+ // sigset by the C library, so avoid testing them.
882+ fn reserved_signo (i : usize ) bool {
883+ return builtin .link_libc and (i >= 32 and i <= 34 );
884+ }
885+
886+ test "sigset add/del" {
863887 if (native_os == .wasi or native_os == .windows )
864888 return error .SkipZigTest ;
865889
866- // https://github.com/ziglang/zig/issues/7427
867- if (native_os == .linux and builtin .target .cpu .arch == .x86 )
890+ var sigset = posix .empty_sigset ;
891+
892+ // See that none are set, then set each one, see that they're all set, then
893+ // remove them all, and then see that none are set.
894+ for (1.. posix .NSIG ) | i | {
895+ try expectEqual (false , posix .sigismember (& sigset , @truncate (i )));
896+ }
897+ for (1.. posix .NSIG ) | i | {
898+ if (! reserved_signo (i )) {
899+ posix .sigaddset (& sigset , @truncate (i ));
900+ }
901+ }
902+ for (1.. posix .NSIG ) | i | {
903+ if (! reserved_signo (i )) {
904+ try expectEqual (true , posix .sigismember (& sigset , @truncate (i )));
905+ }
906+ try expectEqual (false , posix .sigismember (& posix .empty_sigset , @truncate (i )));
907+ }
908+ for (1.. posix .NSIG ) | i | {
909+ if (! reserved_signo (i )) {
910+ posix .sigdelset (& sigset , @truncate (i ));
911+ }
912+ }
913+ for (1.. posix .NSIG ) | i | {
914+ try expectEqual (false , posix .sigismember (& sigset , @truncate (i )));
915+ }
916+ }
917+
918+ test "sigaction" {
919+ if (native_os == .wasi or native_os == .windows )
868920 return error .SkipZigTest ;
869921
870922 // https://github.com/ziglang/zig/issues/15381
871923 if (native_os == .macos and builtin .target .cpu .arch == .x86_64 ) {
872924 return error .SkipZigTest ;
873925 }
874926
927+ const test_signo = posix .SIG .USR1 ;
928+
875929 const S = struct {
876930 var handler_called_count : u32 = 0 ;
877931
878932 fn handler (sig : i32 , info : * const posix.siginfo_t , ctx_ptr : ? * anyopaque ) callconv (.c ) void {
879933 _ = ctx_ptr ;
880934 // Check that we received the correct signal.
881- switch (native_os ) {
882- .netbsd = > {
883- if (sig == posix .SIG .USR1 and sig == info .info .signo )
884- handler_called_count += 1 ;
885- },
886- else = > {
887- if (sig == posix .SIG .USR1 and sig == info .signo )
888- handler_called_count += 1 ;
889- },
935+ const info_sig = switch (native_os ) {
936+ .netbsd = > info .info .signo ,
937+ else = > info .signo ,
938+ };
939+ if (sig == test_signo and sig == info_sig ) {
940+ handler_called_count += 1 ;
890941 }
891942 }
892943 };
@@ -899,39 +950,109 @@ test "sigaction" {
899950 var old_sa : posix.Sigaction = undefined ;
900951
901952 // Install the new signal handler.
902- posix .sigaction (posix . SIG . USR1 , & sa , null );
953+ posix .sigaction (test_signo , & sa , null );
903954
904955 // Check that we can read it back correctly.
905- posix .sigaction (posix . SIG . USR1 , null , & old_sa );
956+ posix .sigaction (test_signo , null , & old_sa );
906957 try testing .expectEqual (& S .handler , old_sa .handler .sigaction .? );
907958 try testing .expect ((old_sa .flags & posix .SA .SIGINFO ) != 0 );
908959
909960 // Invoke the handler.
910- try posix .raise (posix . SIG . USR1 );
911- try testing .expect ( S .handler_called_count == 1 );
961+ try posix .raise (test_signo );
962+ try testing .expectEqual ( 1 , S .handler_called_count );
912963
913964 // Check if passing RESETHAND correctly reset the handler to SIG_DFL
914- posix .sigaction (posix . SIG . USR1 , null , & old_sa );
965+ posix .sigaction (test_signo , null , & old_sa );
915966 try testing .expectEqual (posix .SIG .DFL , old_sa .handler .handler );
916967
917968 // Reinstall the signal w/o RESETHAND and re-raise
918969 sa .flags = posix .SA .SIGINFO ;
919- posix .sigaction (posix . SIG . USR1 , & sa , null );
920- try posix .raise (posix . SIG . USR1 );
921- try testing .expect ( S .handler_called_count == 2 );
970+ posix .sigaction (test_signo , & sa , null );
971+ try posix .raise (test_signo );
972+ try testing .expectEqual ( 2 , S .handler_called_count );
922973
923974 // Now set the signal to ignored
924975 sa .handler = .{ .handler = posix .SIG .IGN };
925976 sa .flags = 0 ;
926- posix .sigaction (posix . SIG . USR1 , & sa , null );
977+ posix .sigaction (test_signo , & sa , null );
927978
928979 // Re-raise to ensure handler is actually ignored
929- try posix .raise (posix . SIG . USR1 );
930- try testing .expect ( S .handler_called_count == 2 );
980+ try posix .raise (test_signo );
981+ try testing .expectEqual ( 2 , S .handler_called_count );
931982
932983 // Ensure that ignored state is returned when querying
933- posix .sigaction (posix .SIG .USR1 , null , & old_sa );
934- try testing .expectEqual (posix .SIG .IGN , old_sa .handler .handler .? );
984+ posix .sigaction (test_signo , null , & old_sa );
985+ try testing .expectEqual (posix .SIG .IGN , old_sa .handler .handler );
986+ }
987+
988+ test "sigset_t bits" {
989+ if (native_os == .wasi or native_os == .windows )
990+ return error .SkipZigTest ;
991+
992+ const S = struct {
993+ var expected_sig : i32 = undefined ;
994+ var handler_called_count : u32 = 0 ;
995+
996+ fn handler (sig : i32 , info : * const posix.siginfo_t , ctx_ptr : ? * anyopaque ) callconv (.c ) void {
997+ _ = ctx_ptr ;
998+
999+ const info_sig = switch (native_os ) {
1000+ .netbsd = > info .info .signo ,
1001+ else = > info .signo ,
1002+ };
1003+ if (sig == expected_sig and sig == info_sig ) {
1004+ handler_called_count += 1 ;
1005+ }
1006+ }
1007+ };
1008+
1009+ const self_pid = posix .system .getpid ();
1010+
1011+ // To check that sigset_t mapping matches kernel (think u32/u64
1012+ // mismatches on big-endian), try sending a blocked signal to make
1013+ // sure the mask matches the signal.
1014+ inline for ([_ ]usize { posix .SIG .INT , posix .SIG .USR1 , 62 , 94 , 126 }) | test_signo | {
1015+ if (test_signo >= posix .NSIG ) continue ;
1016+
1017+ S .expected_sig = test_signo ;
1018+ S .handler_called_count = 0 ;
1019+
1020+ var sa : posix.Sigaction = .{
1021+ .handler = .{ .sigaction = & S .handler },
1022+ .mask = posix .empty_sigset ,
1023+ .flags = posix .SA .SIGINFO | posix .SA .RESETHAND ,
1024+ };
1025+ var old_sa : posix.Sigaction = undefined ;
1026+
1027+ // Install the new signal handler.
1028+ posix .sigaction (test_signo , & sa , & old_sa );
1029+
1030+ // block the signal and see that its delayed until unblocked
1031+ var block_one = posix .empty_sigset ;
1032+ _ = posix .sigaddset (& block_one , test_signo );
1033+ posix .sigprocmask (posix .SIG .BLOCK , & block_one , null );
1034+
1035+ // qemu maps target signals to host signals 1-to-1, so targets
1036+ // with more signals than the host will fail to send the signal.
1037+ const rc = posix .system .kill (self_pid , test_signo );
1038+ switch (posix .errno (rc )) {
1039+ .SUCCESS = > {
1040+ // See that the signal is blocked, then unblocked
1041+ try testing .expectEqual (0 , S .handler_called_count );
1042+ posix .sigprocmask (posix .SIG .UNBLOCK , & block_one , null );
1043+ try testing .expectEqual (1 , S .handler_called_count );
1044+ },
1045+ .INVAL = > {
1046+ // Signal won't get delviered. Just clean up.
1047+ posix .sigprocmask (posix .SIG .UNBLOCK , & block_one , null );
1048+ try testing .expectEqual (0 , S .handler_called_count );
1049+ },
1050+ else = > | errno | return posix .unexpectedErrno (errno ),
1051+ }
1052+
1053+ // Restore original handler
1054+ posix .sigaction (test_signo , & old_sa , null );
1055+ }
9351056}
9361057
9371058test "dup & dup2" {
0 commit comments