| ... | ... | @@ -442,6 +442,7 @@ fn getRandomBytesDevURandom(buf: []u8) !void { |
| 442 | 442 | /// Causes abnormal process termination. |
| 443 | 443 | /// If linking against libc, this calls the abort() libc function. Otherwise |
| 444 | 444 | /// it raises SIGABRT followed by SIGKILL and finally lo |
| 445 | /// Invokes the current signal handler for SIGABRT, if any. |
| 445 | 446 | pub fn abort() noreturn { |
| 446 | 447 | @setCold(true); |
| 447 | 448 | // MSVCRT abort() sometimes opens a popup window which is undesirable, so |
| ... | ... | @@ -454,12 +455,44 @@ pub fn abort() noreturn { |
| 454 | 455 | windows.kernel32.ExitProcess(3); |
| 455 | 456 | } |
| 456 | 457 | if (!builtin.link_libc and builtin.os.tag == .linux) { |
| 458 | // The Linux man page says that the libc abort() function |
| 459 | // "first unblocks the SIGABRT signal", but this is a footgun |
| 460 | // for user-defined signal handlers that want to restore some state in |
| 461 | // some program sections and crash in others. |
| 462 | // So, the user-installed SIGABRT handler is run, if present. |
| 457 | 463 | raise(SIG.ABRT) catch {}; |
| 458 | 464 | |
| 459 | | // TODO the rest of the implementation of abort() from musl libc here |
| 465 | // Disable all signal handlers. |
| 466 | sigprocmask(SIG.BLOCK, &linux.all_mask, null); |
| 460 | 467 | |
| 468 | // Only one thread may proceed to the rest of abort(). |
| 469 | if (!builtin.single_threaded) { |
| 470 | const global = struct { |
| 471 | var abort_entered: bool = false; |
| 472 | }; |
| 473 | while (@cmpxchgWeak(bool, &global.abort_entered, false, true, .SeqCst, .SeqCst)) |_| {} |
| 474 | } |
| 475 | |
| 476 | // Install default handler so that the tkill below will terminate. |
| 477 | const sigact = Sigaction{ |
| 478 | .handler = .{ .sigaction = SIG.DFL }, |
| 479 | .mask = undefined, |
| 480 | .flags = undefined, |
| 481 | .restorer = undefined, |
| 482 | }; |
| 483 | sigaction(SIG.ABRT, &sigact, null) catch |err| switch (err) { |
| 484 | error.OperationNotSupported => unreachable, |
| 485 | }; |
| 486 | |
| 487 | _ = linux.tkill(linux.gettid(), SIG.ABRT); |
| 488 | |
| 489 | const sigabrtmask: linux.sigset_t = [_]u32{0} ** 31 ++ [_]u32{1 << (SIG.ABRT - 1)}; |
| 490 | sigprocmask(SIG.UNBLOCK, &sigabrtmask, null); |
| 491 | |
| 492 | // Beyond this point should be unreachable. |
| 493 | @intToPtr(*allowzero volatile u8, 0).* = 0; |
| 461 | 494 | raise(SIG.KILL) catch {}; |
| 462 | | exit(127); |
| 495 | exit(127); // Pid 1 might not be signalled in some containers. |
| 463 | 496 | } |
| 464 | 497 | if (builtin.os.tag == .uefi) { |
| 465 | 498 | exit(0); // TODO choose appropriate exit code |
| ... | ... | @@ -485,13 +518,13 @@ pub fn raise(sig: u8) RaiseError!void { |
| 485 | 518 | if (builtin.os.tag == .linux) { |
| 486 | 519 | var set: sigset_t = undefined; |
| 487 | 520 | // block application signals |
| 488 | | _ = linux.sigprocmask(SIG.BLOCK, &linux.app_mask, &set); |
| 521 | sigprocmask(SIG.BLOCK, &linux.app_mask, &set); |
| 489 | 522 | |
| 490 | 523 | const tid = linux.gettid(); |
| 491 | 524 | const rc = linux.tkill(tid, sig); |
| 492 | 525 | |
| 493 | 526 | // restore signal mask |
| 494 | | _ = linux.sigprocmask(SIG.SETMASK, &set, null); |
| 527 | sigprocmask(SIG.SETMASK, &set, null); |
| 495 | 528 | |
| 496 | 529 | switch (errno(rc)) { |
| 497 | 530 | .SUCCESS => return, |
| ... | ... | @@ -5441,6 +5474,16 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact |
| 5441 | 5474 | } |
| 5442 | 5475 | } |
| 5443 | 5476 | |
| 5477 | /// Sets the thread signal mask. |
| 5478 | pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?*sigset_t) void { |
| 5479 | switch (errno(system.sigprocmask(flags, set, oldset))) { |
| 5480 | .SUCCESS => return, |
| 5481 | .FAULT => unreachable, |
| 5482 | .INVAL => unreachable, |
| 5483 | else => unreachable, |
| 5484 | } |
| 5485 | } |
| 5486 | |
| 5444 | 5487 | pub const FutimensError = error{ |
| 5445 | 5488 | /// times is NULL, or both tv_nsec values are UTIME_NOW, and either: |
| 5446 | 5489 | /// * the effective user ID of the caller does not match the owner |