hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 7ff4a42407ba00629db951113f525ef165575322
parent 4bf2c178534b89e2530654f55950513ec4f18dd3
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sat,  3 Jun 2023 21:48:26 -0400

unix::signal: replace signal type with sig enum

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mos/exec/process+freebsd.ha | 10+++++-----
Mos/exec/process+linux.ha | 8++++----
Mtest/+test.ha | 8++++++--
Munix/signal/+freebsd.ha | 356++++++++++++++++++++++++++++++++++++-------------------------------------------
Munix/signal/+linux.ha | 358++++++++++++++++++++++++++++++++++++-------------------------------------------
Munix/signal/types.ha | 2+-
6 files changed, 342 insertions(+), 400 deletions(-)

diff --git a/os/exec/process+freebsd.ha b/os/exec/process+freebsd.ha @@ -159,7 +159,7 @@ export fn peekany() ((process, status) | void | error) = { export type exited = int; // The signal number which caused a process to terminate. -export type signaled = int; +export type signaled = signal::sig; // The exit status of a process. export type exit_status = (exited | signaled); @@ -208,15 +208,15 @@ export fn check(stat: *status) (void | !exit_status) = { return exit(stat); }; -// Terminates a process. On FreeBSD, this sends [[unix::signal::SIGTERM]] to the -// process. +// Terminates a process. On FreeBSD, this sends [[unix::signal::sig::TERM]] to +// the process. export fn kill(proc: process) (void | errors::error) = { - return sig(proc, signal::SIGTERM); + return sig(proc, signal::sig::TERM); }; // Sends a signal to a child process. This function is only supported on // Unix-like systems. -export fn sig(proc: process, sig: signal::signal) (void | errors::error) = { +export fn sig(proc: process, sig: signal::sig) (void | errors::error) = { match (rt::kill(proc, sig)) { case let errno: rt::errno => return errors::errno(errno); diff --git a/os/exec/process+linux.ha b/os/exec/process+linux.ha @@ -144,7 +144,7 @@ export fn peekany() ((process, status) | void | error) = { export type exited = int; // The signal number which caused a process to terminate. -export type signaled = int; +export type signaled = signal::sig; // The exit status of a process. export type exit_status = (exited | signaled); @@ -193,15 +193,15 @@ export fn check(stat: *status) (void | !exit_status) = { return exit(stat); }; -// Terminates a process. On Linux, this sends [[unix::signal::SIGTERM]] to the +// Terminates a process. On Linux, this sends [[unix::signal::sig::TERM]] to the // process. export fn kill(proc: process) (void | errors::error) = { - return sig(proc, signal::SIGTERM); + return sig(proc, signal::sig::TERM); }; // Sends a signal to a child process. This function is only supported on // Unix-like systems. -export fn sig(proc: process, sig: signal::signal) (void | errors::error) = { +export fn sig(proc: process, sig: signal::sig) (void | errors::error) = { match (rt::kill(proc, sig)) { case let errno: rt::errno => return errors::errno(errno); diff --git a/test/+test.ha b/test/+test.ha @@ -142,7 +142,7 @@ export @symbol("__test_main") fn main() size = { }; fn do_test(ctx: *context, test: test) void = { - signal::handle(signal::SIGSEGV, &handle_segv, signal::flag::NODEFER); + signal::handle(signal::sig::SEGV, &handle_segv, signal::flag::NODEFER); bufio::reset(&ctx.stdout); bufio::reset(&ctx.stderr); @@ -268,7 +268,11 @@ fn dots(n: size) void = { }; }; -fn handle_segv(sig: int, info: *signal::siginfo, ucontext: *void) void = { +fn handle_segv( + sig: signal::sig, + info: *signal::siginfo, + ucontext: *void, +) void = { rt::longjmp(&jmpbuf, 2); }; diff --git a/unix/signal/+freebsd.ha b/unix/signal/+freebsd.ha @@ -9,7 +9,7 @@ use rt; // to use via [[sigset]]; if the latter is provided no more than one may be // used. export fn handle( - signum: signal, + signum: sig, handler: *handler, opt: (flag | sigset)... ) sigaction = { @@ -46,7 +46,7 @@ export fn handle( }; // Restores previous signal behavior following [[handle]]. -export fn restore(signum: signal, action: *sigaction) void = { +export fn restore(signum: sig, action: *sigaction) void = { match (rt::sigaction(signum, action, null)) { case int => yield; @@ -56,56 +56,56 @@ export fn restore(signum: signal, action: *sigaction) void = { }; // Unregisters signal handlers for the specified signal. -export fn reset(signum: signal) void = { +export fn reset(signum: sig) void = { handle(signum, rt::SIG_DFL: *handler); }; // Unregisters all signal handlers. export fn resetall() void = { - // SIGKILL and SIGSTOP deliberately omitted; see sigaction(2) - reset(SIGHUP); - reset(SIGINT); - reset(SIGQUIT); - reset(SIGILL); - reset(SIGTRAP); - reset(SIGABRT); - reset(SIGEMT); - reset(SIGFPE); - reset(SIGBUS); - reset(SIGSEGV); - reset(SIGSYS); - reset(SIGPIPE); - reset(SIGALRM); - reset(SIGTERM); - reset(SIGURG); - reset(SIGTSTP); - reset(SIGCONT); - reset(SIGCHLD); - reset(SIGTTIN); - reset(SIGTTOU); - reset(SIGIO); - reset(SIGXCPU); - reset(SIGXFSZ); - reset(SIGVTALRM); - reset(SIGPROF); - reset(SIGWINCH); - reset(SIGINFO); - reset(SIGUSR1); - reset(SIGUSR2); - reset(SIGTHR); - reset(SIGLIBRT); + // sig::KILL and sig::STOP deliberately omitted; see sigaction(2) + reset(sig::HUP); + reset(sig::INT); + reset(sig::QUIT); + reset(sig::ILL); + reset(sig::TRAP); + reset(sig::ABRT); + reset(sig::EMT); + reset(sig::FPE); + reset(sig::BUS); + reset(sig::SEGV); + reset(sig::SYS); + reset(sig::PIPE); + reset(sig::ALRM); + reset(sig::TERM); + reset(sig::URG); + reset(sig::TSTP); + reset(sig::CONT); + reset(sig::CHLD); + reset(sig::TTIN); + reset(sig::TTOU); + reset(sig::IO); + reset(sig::XCPU); + reset(sig::XFSZ); + reset(sig::VTALRM); + reset(sig::PROF); + reset(sig::WINCH); + reset(sig::INFO); + reset(sig::USR1); + reset(sig::USR2); + reset(sig::THR); + reset(sig::LIBRT); }; // Prevents given signal from arriving to the current process. // One common use case is to ignore SIGCHLD to avoid zombie child processes. -export fn ignore(signum: signal) void = { +export fn ignore(signum: sig) void = { handle(signum, rt::SIG_IGN: *handler); }; // Adds the given list of signals to the process's current signal mask, // returning the old signal mask. This is a convenience function around // [[setprocmask]]. -export fn block(signals: signal...) sigset = { +export fn block(signals: sig...) sigset = { let new = newsigset(signals...); return setprocmask(how::BLOCK, &new); }; @@ -113,7 +113,7 @@ export fn block(signals: signal...) sigset = { // Removes the given list of signals from the process's current signal mask, // returning the old signal mask. This is a convenience function around // [[setprocmask]]. -export fn unblock(signals: signal...) sigset = { +export fn unblock(signals: sig...) sigset = { let new = newsigset(signals...); return setprocmask(how::UNBLOCK, &new); }; @@ -148,7 +148,7 @@ export type sigset = rt::sigset; // Creates a new signal set filled in with the provided signals (or empty if // none are provided). -export fn newsigset(items: signal...) sigset = { +export fn newsigset(items: sig...) sigset = { let set = sigset { ... }; rt::sigemptyset(&set); sigset_add(&set, items...); @@ -161,21 +161,21 @@ export fn sigset_empty(set: *sigset) void = { }; // Adds signals to a [[sigset]]. -export fn sigset_add(set: *sigset, items: signal...) void = { +export fn sigset_add(set: *sigset, items: sig...) void = { for (let i = 0z; i < len(items); i += 1) { rt::sigaddset(set, items[i])!; }; }; // Removes signals from a [[sigset]]. -export fn sigset_del(set: *sigset, items: signal...) void = { +export fn sigset_del(set: *sigset, items: sig...) void = { for (let i = 0z; i < len(items); i += 1) { rt::sigdelset(set, items[i])!; }; }; // Returns true if the given signal is a member of this [[sigset]]. -export fn sigset_member(set: *sigset, item: signal) bool = { +export fn sigset_member(set: *sigset, item: sig) bool = { return rt::sigismember(set, item)!; }; @@ -187,7 +187,7 @@ export fn sigset_member(set: *sigset, item: signal) bool = { export type siginfo = union { struct { // The signal number being delivered. - signo: signal, + signo: sig, // The errno, if any, associated with this signal. See // [[errors::errno]] to convert to a Hare-native error. errno: rt::errno, @@ -210,60 +210,60 @@ export type code = enum int { TKILL = -6, // sent by userspace program (tkill, tgkill) ASYNCNL = -60, - ILLOPC = 1, // SIGILL: illegal opcode - ILLOPN = 2, // SIGILL: illegal operand - ILLADR = 3, // SIGILL: illegal addressing mode - ILLTRP = 4, // SIGILL: illegal trap - PRVOPC = 5, // SIGILL: privileged opcode - PRVREG = 6, // SIGILL: privileged register - COPROC = 7, // SIGILL: coprocessor error - BADSTK = 8, // SIGILL: internal stack error - - INTOVF = 1, // SIGFPE: integer overflow - INTDIV = 2, // SIGFPE: integer divide by zero - FLTDIV = 3, // SIGFPE: floating-point divide by zero - FLTOVF = 4, // SIGFPE: floating-point overflow - FLTUND = 5, // SIGFPE: floating-point underflow - FLTRES = 6, // SIGFPE: floating-point inexact result - FLTINV = 7, // SIGFPE: invalid floating-point operation - FLTSUB = 8, // SIGFPE: subscript out of range - - MAPERR = 1, // SIGSEGV: address not mapped to object - ACCERR = 2, // SIGSEGV: invalid permissions for mapped object - PKUERR = 100, // SIGSEGV: access was denied by memory protection keys (x86_64) - - ADRALN = 1, // SIGBUS: invalid address alignment - ADRERR = 2, // SIGBUS: nonexistent physical address - OBJERR = 3, // SIGBUS: object-specific hardware error - OOMERR = 100, // SIGBUS: out of memory - - BRKPT = 1, // SIGTRAP: process breakpoint - TRACE = 2, // SIGTRAP: process trace trap - DTRACE = 3, // SIGTRAP: DTrace induced trap - CAP = 4, // SIGTRAP: capabilities protection trap - - EXITED = 1, // SIGCHLD: child exited - KILLED = 2, // SIGCHLD: child terminated abnormally without a core file - DUMPED = 3, // SIGCHLD: child terminated abnormally with a core file - TRAPPED = 4, // SIGCHLD: traced child has trapped - STOPPED = 5, // SIGCHLD: child has stopped - CONTINUED = 6, // SIGCHLD: stopped child has continued - - IN = 1, // SIGPOLL: data input available - OUT = 2, // SIGPOLL: output buffers available - MSG = 3, // SIGPOLL: input message available - ERR = 4, // SIGPOLL: I/O error - PRI = 5, // SIGPOLL: high priority input available - HUP = 6, // SIGPOLL: device disconnected + ILLOPC = 1, // sig::ILL: illegal opcode + ILLOPN = 2, // sig::ILL: illegal operand + ILLADR = 3, // sig::ILL: illegal addressing mode + ILLTRP = 4, // sig::ILL: illegal trap + PRVOPC = 5, // sig::ILL: privileged opcode + PRVREG = 6, // sig::ILL: privileged register + COPROC = 7, // sig::ILL: coprocessor error + BADSTK = 8, // sig::ILL: internal stack error + + INTOVF = 1, // sig::FPE: integer overflow + INTDIV = 2, // sig::FPE: integer divide by zero + FLTDIV = 3, // sig::FPE: floating-point divide by zero + FLTOVF = 4, // sig::FPE: floating-point overflow + FLTUND = 5, // sig::FPE: floating-point underflow + FLTRES = 6, // sig::FPE: floating-point inexact result + FLTINV = 7, // sig::FPE: invalid floating-point operation + FLTSUB = 8, // sig::FPE: subscript out of range + + MAPERR = 1, // sig::SEGV: address not mapped to object + ACCERR = 2, // sig::SEGV: invalid permissions for mapped object + PKUERR = 100, // sig::SEGV: access was denied by memory protection keys (x86_64) + + ADRALN = 1, // sig::BUS: invalid address alignment + ADRERR = 2, // sig::BUS: nonexistent physical address + OBJERR = 3, // sig::BUS: object-specific hardware error + OOMERR = 100, // sig::BUS: out of memory + + BRKPT = 1, // sig::TRAP: process breakpoint + TRACE = 2, // sig::TRAP: process trace trap + DTRACE = 3, // sig::TRAP: DTrace induced trap + CAP = 4, // sig::TRAP: capabilities protection trap + + EXITED = 1, // sig::CHLD: child exited + KILLED = 2, // sig::CHLD: child terminated abnormally without a core file + DUMPED = 3, // sig::CHLD: child terminated abnormally with a core file + TRAPPED = 4, // sig::CHLD: traced child has trapped + STOPPED = 5, // sig::CHLD: child has stopped + CONTINUED = 6, // sig::CHLD: stopped child has continued + + IN = 1, // sig::POLL: data input available + OUT = 2, // sig::POLL: output buffers available + MSG = 3, // sig::POLL: input message available + ERR = 4, // sig::POLL: I/O error + PRI = 5, // sig::POLL: high priority input available + HUP = 6, // sig::POLL: device disconnected }; // Flags used to configure the behavior of a signal handler. export type flag = enum int { - // For use with [[SIGCHLD]]. Prevents notifications when child processes - // stop (e.g. via [[SIGSTOP]]) or resume (i.e. [[SIGCONT]]). + // For use with sig::CHLD. Prevents notifications when child processes + // stop (e.g. via sig::STOP) or resume (i.e. sig::CONT). NOCLDSTOP = rt::SA_NOCLDSTOP: int, - // For use with [[SIGCHLD]]. Do not transform children into zombies when - // they terminate. Note that POSIX leaves the delivery of [[SIGCHLD]] + // For use with sig::CHLD. Do not transform children into zombies when + // they terminate. Note that POSIX leaves the delivery of sig::CHLD // unspecified when this flag is present; some systems will still // deliver a signal and others may not. NOCLDWAIT = rt::SA_NOCLDWAIT: int, @@ -282,143 +282,111 @@ export type flag = enum int { RESTART = rt::SA_RESTART: int, }; -export type signal = int; - -// Hangup. -export def SIGHUP: signal = rt::SIGHUP; -// Terminal interrupt signal. -export def SIGINT: signal = rt::SIGINT; -// Terminal quit signal. -export def SIGQUIT: signal = rt::SIGQUIT; -// Illegal instruction. -export def SIGILL: signal = rt::SIGILL; -// Trace/breakposignal trap. -export def SIGTRAP: signal = rt::SIGTRAP; -// Process abort signal. -export def SIGABRT: signal = rt::SIGABRT; -// Emulate instruction executed. -export def SIGEMT: signal = rt::SIGEMT; -// Erroneous arithmetic operation. -export def SIGFPE: signal = rt::SIGFPE; -// Kill (cannot be caught or ignored). -export def SIGKILL: signal = rt::SIGKILL; -// Access to an undefined portion of a memory object. -export def SIGBUS: signal = rt::SIGBUS; -// Invalid memory reference. -export def SIGSEGV: signal = rt::SIGSEGV; -// Bad system call. -export def SIGSYS: signal = rt::SIGSYS; -// Write on a pipe with no one to read it. -export def SIGPIPE: signal = rt::SIGPIPE; -// Alarm clock. -export def SIGALRM: signal = rt::SIGALRM; -// Termination signal. -export def SIGTERM: signal = rt::SIGTERM; -// High bandwidth data is available at a socket. -export def SIGURG: signal = rt::SIGURG; -// Stop executing (cannot be caught or ignored). -export def SIGSTOP: signal = rt::SIGSTOP; -// Terminal stop signal. -export def SIGTSTP: signal = rt::SIGTSTP; -// Continue executing, if stopped. -export def SIGCONT: signal = rt::SIGCONT; -// Child process terminated, stopped, or continued. -export def SIGCHLD: signal = rt::SIGCHLD; -// Background process attempting read. -export def SIGTTIN: signal = rt::SIGTTIN; -// Background process attempting write. -export def SIGTTOU: signal = rt::SIGTTOU; -// I/O now possible. -export def SIGIO: signal = rt::SIGIO; -// CPU time limit exceeded. -export def SIGXCPU: signal = rt::SIGXCPU; -// File size limit exceeded. -export def SIGXFSZ: signal = rt::SIGXFSZ; -// Virtual timer expired. -export def SIGVTALRM: signal = rt::SIGVTALRM; -// Profiling timer expired. -export def SIGPROF: signal = rt::SIGPROF; -// Window resize signal. -export def SIGWINCH: signal = rt::SIGWINCH; -// Status request from keyboard. -export def SIGINFO: signal = rt::SIGINFO; -// User-defined signal 1. -export def SIGUSR1: signal = rt::SIGUSR1; -// User-defined signal 2. -export def SIGUSR2: signal = rt::SIGUSR2; -// Thread interrupt. -export def SIGTHR: signal = rt::SIGTHR; -// Real-time library interrupt. -export def SIGLIBRT: signal = rt::SIGLIBRT; +// All possible signals. +export type sig = enum int { + HUP = rt::SIGHUP, // Hangup. + INT = rt::SIGINT, // Terminal interrupt. + QUIT = rt::SIGQUIT, // Terminal quit. + ILL = rt::SIGILL, // Illegal instruction. + TRAP = rt::SIGTRAP, // Trace/breakpoint trap. + ABRT = rt::SIGABRT, // Process abort. + EMT = rt::SIGEMT, // Emulate instruction executed. + FPE = rt::SIGFPE, // Erroneous arithmetic operation. + KILL = rt::SIGKILL, // Kill (cannot be caught or ignored). + BUS = rt::SIGBUS, // Access to an undefined portion of a memory object. + SEGV = rt::SIGSEGV, // Invalid memory reference. + SYS = rt::SIGSYS, // Bad system call. + PIPE = rt::SIGPIPE, // Write on a pipe with no one to read it. + ALRM = rt::SIGALRM, // Alarm clock. + TERM = rt::SIGTERM, // Termination. + URG = rt::SIGURG, // High bandwidth data is available at a socket. + STOP = rt::SIGSTOP, // Stop executing (cannot be caught or ignored). + TSTP = rt::SIGTSTP, // Terminal stop. + CONT = rt::SIGCONT, // Continue executing, if stopped. + CHLD = rt::SIGCHLD, // Child process terminated, stopped, or continued. + TTIN = rt::SIGTTIN, // Background process attempting read. + TTOU = rt::SIGTTOU, // Background process attempting write. + IO = rt::SIGIO, // I/O now possible. + XCPU = rt::SIGXCPU, // CPU time limit exceeded. + XFSZ = rt::SIGXFSZ, // File size limit exceeded. + VTALRM = rt::SIGVTALRM, // Virtual timer expired. + PROF = rt::SIGPROF, // Profiling timer expired. + WINCH = rt::SIGWINCH, // Window resize. + INFO = rt::SIGINFO, // Status request from keyboard. + USR1 = rt::SIGUSR1, // User-defined signal 1. + USR2 = rt::SIGUSR2, // User-defined signal 2. + THR = rt::SIGTHR, // Thread interrupt. + LIBRT = rt::SIGLIBRT, // Real-time library interrupt. +}; // Returns the human friendly name of a given signal. -export fn signame(sig: signal) const str = { +export fn signame(sig: sig) const str = { switch (sig) { - case SIGHUP => + case sig::HUP => return "SIGHUP"; - case SIGINT => + case sig::INT => return "SIGINT"; - case SIGQUIT => + case sig::QUIT => return "SIGQUIT"; - case SIGILL => + case sig::ILL => return "SIGILL"; - case SIGTRAP => + case sig::TRAP => return "SIGTRAP"; - case SIGABRT => + case sig::ABRT => return "SIGABRT"; - case SIGEMT => + case sig::EMT => return "SIGEMT"; - case SIGFPE => + case sig::FPE => return "SIGFPE"; - case SIGKILL => + case sig::KILL => return "SIGKILL"; - case SIGBUS => + case sig::BUS => return "SIGBUS"; - case SIGSEGV => + case sig::SEGV => return "SIGSEGV"; - case SIGSYS => + case sig::SYS => return "SIGSYS"; - case SIGPIPE => + case sig::PIPE => return "SIGPIPE"; - case SIGALRM => + case sig::ALRM => return "SIGALRM"; - case SIGTERM => + case sig::TERM => return "SIGTERM"; - case SIGURG => + case sig::URG => return "SIGURG"; - case SIGSTOP => + case sig::STOP => return "SIGSTOP"; - case SIGTSTP => + case sig::TSTP => return "SIGTSTP"; - case SIGCONT => + case sig::CONT => return "SIGCONT"; - case SIGCHLD => + case sig::CHLD => return "SIGCHLD"; - case SIGTTIN => + case sig::TTIN => return "SIGTTIN"; - case SIGTTOU => + case sig::TTOU => return "SIGTTOU"; - case SIGIO => + case sig::IO => return "SIGIO"; - case SIGXCPU => + case sig::XCPU => return "SIGXCPU"; - case SIGXFSZ => + case sig::XFSZ => return "SIGXFSZ"; - case SIGVTALRM => + case sig::VTALRM => return "SIGVTALRM"; - case SIGPROF => + case sig::PROF => return "SIGPROF"; - case SIGWINCH => + case sig::WINCH => return "SIGWINCH"; - case SIGINFO => + case sig::INFO => return "SIGINFO"; - case SIGUSR1 => + case sig::USR1 => return "SIGUSR1"; - case SIGUSR2 => + case sig::USR2 => return "SIGUSR2"; - case SIGTHR => + case sig::THR => return "SIGTHR"; - case SIGLIBRT => + case sig::LIBRT => return "SIGLIBRT"; case => abort(); // unreachable }; diff --git a/unix/signal/+linux.ha b/unix/signal/+linux.ha @@ -11,7 +11,7 @@ use rt; // to use via [[sigset]]; if the latter is provided no more than one may be // used. export fn handle( - signum: signal, + signum: sig, handler: *handler, opt: (flag | sigset)... ) sigaction = { @@ -52,7 +52,7 @@ export fn handle( }; // Restores previous signal behavior following [[handle]]. -export fn restore(signum: signal, action: *sigaction) void = { +export fn restore(signum: sig, action: *sigaction) void = { match (rt::sigaction(signum, action, null)) { case int => yield; @@ -62,54 +62,54 @@ export fn restore(signum: signal, action: *sigaction) void = { }; // Unregisters signal handlers for the specified signal. -export fn reset(signum: signal) void = { +export fn reset(signum: sig) void = { handle(signum, rt::SIG_DFL: *handler); }; // Unregisters all signal handlers. export fn resetall() void = { - // SIGKILL and SIGSTOP deliberately omitted; see sigaction(2) - reset(SIGHUP); - reset(SIGINT); - reset(SIGQUIT); - reset(SIGILL); - reset(SIGTRAP); - reset(SIGABRT); - reset(SIGBUS); - reset(SIGFPE); - reset(SIGUSR1); - reset(SIGSEGV); - reset(SIGUSR2); - reset(SIGPIPE); - reset(SIGALRM); - reset(SIGTERM); - reset(SIGCHLD); - reset(SIGCONT); - reset(SIGTSTP); - reset(SIGTTIN); - reset(SIGTTOU); - reset(SIGURG); - reset(SIGXCPU); - reset(SIGXFSZ); - reset(SIGVTALRM); - reset(SIGPROF); - reset(SIGWINCH); - reset(SIGIO); - reset(SIGPOLL); - reset(SIGPWR); - reset(SIGSYS); + // sig::KILL and sig::STOP deliberately omitted; see sigaction(2) + reset(sig::HUP); + reset(sig::INT); + reset(sig::QUIT); + reset(sig::ILL); + reset(sig::TRAP); + reset(sig::ABRT); + reset(sig::BUS); + reset(sig::FPE); + reset(sig::USR1); + reset(sig::SEGV); + reset(sig::USR2); + reset(sig::PIPE); + reset(sig::ALRM); + reset(sig::TERM); + reset(sig::CHLD); + reset(sig::CONT); + reset(sig::TSTP); + reset(sig::TTIN); + reset(sig::TTOU); + reset(sig::URG); + reset(sig::XCPU); + reset(sig::XFSZ); + reset(sig::VTALRM); + reset(sig::PROF); + reset(sig::WINCH); + reset(sig::IO); + reset(sig::POLL); + reset(sig::PWR); + reset(sig::SYS); }; // Prevents given signal from arriving to the current process. // One common use case is to ignore SIGCHLD to avoid zombie child processes. -export fn ignore(signum: signal) void = { +export fn ignore(signum: sig) void = { handle(signum, rt::SIG_IGN: *handler); }; // Adds the given list of signals to the process's current signal mask, // returning the old signal mask. This is a convenience function around // [[setprocmask]]. -export fn block(signals: signal...) sigset = { +export fn block(signals: sig...) sigset = { let new = newsigset(signals...); return setprocmask(how::BLOCK, &new); }; @@ -117,7 +117,7 @@ export fn block(signals: signal...) sigset = { // Removes the given list of signals from the process's current signal mask, // returning the old signal mask. This is a convenience function around // [[setprocmask]]. -export fn unblock(signals: signal...) sigset = { +export fn unblock(signals: sig...) sigset = { let new = newsigset(signals...); return setprocmask(how::UNBLOCK, &new); }; @@ -152,7 +152,7 @@ export type sigset = rt::sigset; // Creates a new signal set filled in with the provided signals (or empty if // none are provided). -export fn newsigset(items: signal...) sigset = { +export fn newsigset(items: sig...) sigset = { let set = sigset { ... }; rt::sigemptyset(&set); sigset_add(&set, items...); @@ -165,21 +165,21 @@ export fn sigset_empty(set: *sigset) void = { }; // Adds signals to a [[sigset]]. -export fn sigset_add(set: *sigset, items: signal...) void = { +export fn sigset_add(set: *sigset, items: sig...) void = { for (let i = 0z; i < len(items); i += 1) { rt::sigaddset(set, items[i])!; }; }; // Removes signals from a [[sigset]]. -export fn sigset_del(set: *sigset, items: signal...) void = { +export fn sigset_del(set: *sigset, items: sig...) void = { for (let i = 0z; i < len(items); i += 1) { rt::sigdelset(set, items[i])!; }; }; // Returns true if the given signal is a member of this [[sigset]]. -export fn sigset_member(set: *sigset, item: signal) bool = { +export fn sigset_member(set: *sigset, item: sig) bool = { return rt::sigismember(set, item)!; }; @@ -191,7 +191,7 @@ export fn sigset_member(set: *sigset, item: signal) bool = { export type siginfo = union { struct { // The signal number being delivered. - signo: signal, + signo: sig, // The errno, if any, associated with this signal. See // [[errors::errno]] to convert to a Hare-native error. errno: rt::errno, @@ -214,65 +214,65 @@ export type code = enum int { TKILL = -6, // sent by userspace program (tkill, tgkill) ASYNCNL = -60, - ILLOPC = 1, // SIGILL: illegal opcode - ILLOPN = 2, // SIGILL: illegal operand - ILLADR = 3, // SIGILL: illegal addressing mode - ILLTRP = 4, // SIGILL: illegal trap - PRVOPC = 5, // SIGILL: privileged opcode - PRVREG = 6, // SIGILL: privileged register - COPROC = 7, // SIGILL: coprocessor error - BADSTK = 8, // SIGILL: internal stack error - - INTDIV = 1, // SIGFPE: integer divide by zero - INTOVF = 2, // SIGFPE: integer overflow - FLTDIV = 3, // SIGFPE: floating-point divide by zero - FLTOVF = 4, // SIGFPE: floating-point overflow - FLTUND = 5, // SIGFPE: floating-point underflow - FLTRES = 6, // SIGFPE: floating-point inexact result - FLTINV = 7, // SIGFPE: invalid floating-point operation - FLTSUB = 8, // SIGFPE: subscript out of range - - MAPERR = 1, // SIGSEGV: address not mapped to object - ACCERR = 2, // SIGSEGV: invalid permissions for mapped object - BNDERR = 3, // SIGSEGV: failed address bound checks - PKUERR = 4, // SIGSEGV: access was denied by memory protection keys - MTEAERR = 8, // SIGSEGV - MTESERR = 9, // SIGSEGV - - ADRALN = 1, // SIGBUS: invalid address alignment - ADRERR = 2, // SIGBUS: nonexistent physical address - OBJERR = 3, // SIGBUS: object-specific hardware error - MCEERR_AR = 4, // SIGBUS: hardware memory error consumed on a machine check; action required - MCEERR_AO = 5, // SIGBUS: hardware memory error detected in process but not consumed; action optional - - BRKPT = 1, // SIGTRAP: process breakpoint - TRACE = 2, // SIGTRAP: process trace trap - BRANCH = 3, // SIGTRAP: process taken branch trap - HWBKPT = 4, // SIGTRAP: hardware breakpoint/watchpoint - UNK = 5, // SIGTRAP - - EXITED = 1, // SIGCHLD: child exited - KILLED = 2, // SIGCHLD: child terminated abnormally without a core file - DUMPED = 3, // SIGCHLD: child terminated abnormally with a core file - TRAPPED = 4, // SIGCHLD: traced child has trapped - STOPPED = 5, // SIGCHLD: child has stopped - CONTINUED = 6, // SIGCHLD: stopped child has continued - - IN = 1, // SIGPOLL: data input available - OUT = 2, // SIGPOLL: output buffers available - MSG = 3, // SIGPOLL: input message available - ERR = 4, // SIGPOLL: I/O error - PRI = 5, // SIGPOLL: high priority input available - HUP = 6, // SIGPOLL: device disconnected + ILLOPC = 1, // sig::ILL: illegal opcode + ILLOPN = 2, // sig::ILL: illegal operand + ILLADR = 3, // sig::ILL: illegal addressing mode + ILLTRP = 4, // sig::ILL: illegal trap + PRVOPC = 5, // sig::ILL: privileged opcode + PRVREG = 6, // sig::ILL: privileged register + COPROC = 7, // sig::ILL: coprocessor error + BADSTK = 8, // sig::ILL: internal stack error + + INTDIV = 1, // sig::FPE: integer divide by zero + INTOVF = 2, // sig::FPE: integer overflow + FLTDIV = 3, // sig::FPE: floating-point divide by zero + FLTOVF = 4, // sig::FPE: floating-point overflow + FLTUND = 5, // sig::FPE: floating-point underflow + FLTRES = 6, // sig::FPE: floating-point inexact result + FLTINV = 7, // sig::FPE: invalid floating-point operation + FLTSUB = 8, // sig::FPE: subscript out of range + + MAPERR = 1, // sig::SEGV: address not mapped to object + ACCERR = 2, // sig::SEGV: invalid permissions for mapped object + BNDERR = 3, // sig::SEGV: failed address bound checks + PKUERR = 4, // sig::SEGV: access was denied by memory protection keys + MTEAERR = 8, // sig::SEGV + MTESERR = 9, // sig::SEGV + + ADRALN = 1, // sig::BUS: invalid address alignment + ADRERR = 2, // sig::BUS: nonexistent physical address + OBJERR = 3, // sig::BUS: object-specific hardware error + MCEERR_AR = 4, // sig::BUS: hardware memory error consumed on a machine check; action required + MCEERR_AO = 5, // sig::BUS: hardware memory error detected in process but not consumed; action optional + + BRKPT = 1, // sig::TRAP: process breakpoint + TRACE = 2, // sig::TRAP: process trace trap + BRANCH = 3, // sig::TRAP: process taken branch trap + HWBKPT = 4, // sig::TRAP: hardware breakpoint/watchpoint + UNK = 5, // sig::TRAP + + EXITED = 1, // sig::CHLD: child exited + KILLED = 2, // sig::CHLD: child terminated abnormally without a core file + DUMPED = 3, // sig::CHLD: child terminated abnormally with a core file + TRAPPED = 4, // sig::CHLD: traced child has trapped + STOPPED = 5, // sig::CHLD: child has stopped + CONTINUED = 6, // sig::CHLD: stopped child has continued + + IN = 1, // sig::POLL: data input available + OUT = 2, // sig::POLL: output buffers available + MSG = 3, // sig::POLL: input message available + ERR = 4, // sig::POLL: I/O error + PRI = 5, // sig::POLL: high priority input available + HUP = 6, // sig::POLL: device disconnected }; // Flags used to configure the behavior of a signal handler. export type flag = enum int { - // For use with [[SIGCHLD]]. Prevents notifications when child processes - // stop (e.g. via [[SIGSTOP]]) or resume (i.e. [[SIGCONT]]). + // For use with sig::CHLD. Prevents notifications when child processes + // stop (e.g. via sig::STOp) or resume (i.e. sig::CONT). NOCLDSTOP = rt::SA_NOCLDSTOP: int, - // For use with [[SIGCHLD]]. Do not transform children into zombies when - // they terminate. Note that POSIX leaves the delivery of [[SIGCHLD]] + // For use with sig::CHLD. Do not transform children into zombies when + // they terminate. Note that POSIX leaves the delivery of sig::CHLD // unspecified when this flag is present; some systems will still // deliver a signal and others may not. NOCLDWAIT = rt::SA_NOCLDWAIT: int, @@ -291,10 +291,43 @@ export type flag = enum int { RESETHAND = rt::SA_RESETHAND: int, }; -export type signal = int; +// All possible signals. +export type sig = enum int { + HUP = rt::SIGHUP, // Hangup. + INT = rt::SIGINT, // Terminal interrupt. + QUIT = rt::SIGQUIT, // Terminal quit. + ILL = rt::SIGILL, // Illegal instruction. + TRAP = rt::SIGTRAP, // Trace/breakpoint trap. + ABRT = rt::SIGABRT, // Process abort. + BUS = rt::SIGBUS, // Access to an undefined portion of a memory object. + FPE = rt::SIGFPE, // Erroneous arithmetic operation. + KILL = rt::SIGKILL, // Kill (cannot be caught or ignored). + USR1 = rt::SIGUSR1, // User-defined signal 1. + SEGV = rt::SIGSEGV, // Invalid memory reference. + USR2 = rt::SIGUSR2, // User-defined signal 2. + PIPE = rt::SIGPIPE, // Write on a pipe with no one to read it. + ALRM = rt::SIGALRM, // Alarm clock. + TERM = rt::SIGTERM, // Termination. + CHLD = rt::SIGCHLD, // Child process terminated, stopped, or continued. + CONT = rt::SIGCONT, // Continue executing if stopped. + STOP = rt::SIGSTOP, // Stop executing (cannot be caught or ignored). + TSTP = rt::SIGTSTP, // Terminal stop. + TTIN = rt::SIGTTIN, // Background process attempting read. + TTOU = rt::SIGTTOU, // Background process attempting write. + URG = rt::SIGURG, // High bandwidth data is available at a socket. + XCPU = rt::SIGXCPU, // CPU time limit exceeded. + XFSZ = rt::SIGXFSZ, // File size limit exceeded. + VTALRM = rt::SIGVTALRM, // Virtual timer expired. + PROF = rt::SIGPROF, // Profiling timer expired. + WINCH = rt::SIGWINCH, // Window resize signal. + IO = rt::SIGIO, // I/O now possible. + POLL = rt::SIGPOLL, // Pollable event. + PWR = rt::SIGPWR, // Power failure. + SYS = rt::SIGSYS, // Bad system call. +}; // Creates a signal file that handles the given set of signals. -export fn signalfd(signals: signal...) (io::file | errors::error) = { +export fn signalfd(signals: sig...) (io::file | errors::error) = { let sa_mask = newsigset(signals...); match (rt::signalfd(-1, &sa_mask, rt::SFD_CLOEXEC)) { case let fd: int => @@ -306,7 +339,7 @@ export fn signalfd(signals: signal...) (io::file | errors::error) = { // Updates a signalfd with a new set of signals. The signal set is overwritten, // rather than appended to, with the provided set of signals. -export fn update(fd: io::file, signals: signal...) (void | errors::error) = { +export fn update(fd: io::file, signals: sig...) (void | errors::error) = { let sa_mask = newsigset(signals...); match (rt::signalfd(fd, &sa_mask, rt::SFD_CLOEXEC)) { @@ -327,140 +360,77 @@ export fn read(fd: io::file) (siginfo | errors::error) = { assert(z == size(rt::signalfd_siginfo)); }; return siginfo { - signo = si.ssi_signo: signal, + signo = si.ssi_signo: sig, errno = si.ssi_errno: rt::errno, code = si.ssi_code: code, ... }; }; -// Hangup. -export def SIGHUP: signal = rt::SIGHUP; -// Terminal interrupt signal. -export def SIGINT: signal = rt::SIGINT; -// Terminal quit signal. -export def SIGQUIT: signal = rt::SIGQUIT; -// Illegal instruction. -export def SIGILL: signal = rt::SIGILL; -// Trace/breakposignal trap. -export def SIGTRAP: signal = rt::SIGTRAP; -// Process abort signal. -export def SIGABRT: signal = rt::SIGABRT; -// Access to an undefined portion of a memory object. -export def SIGBUS: signal = rt::SIGBUS; -// Erroneous arithmetic operation. -export def SIGFPE: signal = rt::SIGFPE; -// Kill (cannot be caught or ignored). -export def SIGKILL: signal = rt::SIGKILL; -// User-defined signal 1. -export def SIGUSR1: signal = rt::SIGUSR1; -// Invalid memory reference. -export def SIGSEGV: signal = rt::SIGSEGV; -// User-defined signal 2. -export def SIGUSR2: signal = rt::SIGUSR2; -// Write on a pipe with no one to read it. -export def SIGPIPE: signal = rt::SIGPIPE; -// Alarm clock. -export def SIGALRM: signal = rt::SIGALRM; -// Termination signal. -export def SIGTERM: signal = rt::SIGTERM; -// Child process terminated, stopped, or continued. -export def SIGCHLD: signal = rt::SIGCHLD; -// Continue executing, if stopped. -export def SIGCONT: signal = rt::SIGCONT; -// Stop executing (cannot be caught or ignored). -export def SIGSTOP: signal = rt::SIGSTOP; -// Terminal stop signal. -export def SIGTSTP: signal = rt::SIGTSTP; -// Background process attempting read. -export def SIGTTIN: signal = rt::SIGTTIN; -// Background process attempting write. -export def SIGTTOU: signal = rt::SIGTTOU; -// High bandwidth data is available at a socket. -export def SIGURG: signal = rt::SIGURG; -// CPU time limit exceeded. -export def SIGXCPU: signal = rt::SIGXCPU; -// File size limit exceeded. -export def SIGXFSZ: signal = rt::SIGXFSZ; -// Virtual timer expired. -export def SIGVTALRM: signal = rt::SIGVTALRM; -// Profiling timer expired. -export def SIGPROF: signal = rt::SIGPROF; -// Window resize signal. -export def SIGWINCH: signal = rt::SIGWINCH; -// I/O now possible. -export def SIGIO: signal = rt::SIGIO; -// Pollable event. -export def SIGPOLL: signal = rt::SIGPOLL; -// Power failure. -export def SIGPWR: signal = rt::SIGPWR; -// Bad system call. -export def SIGSYS: signal = rt::SIGSYS; - // Returns the human friendly name of a given signal. -export fn signame(sig: signal) const str = { +export fn signame(sig: sig) const str = { switch (sig) { - case SIGHUP => + case sig::HUP => return "SIGHUP"; - case SIGINT => + case sig::INT => return "SIGINT"; - case SIGQUIT => + case sig::QUIT => return "SIGQUIT"; - case SIGILL => + case sig::ILL => return "SIGILL"; - case SIGTRAP => + case sig::TRAP => return "SIGTRAP"; - case SIGABRT => + case sig::ABRT => return "SIGABRT"; - case SIGBUS => + case sig::BUS => return "SIGBUS"; - case SIGFPE => + case sig::FPE => return "SIGFPE"; - case SIGKILL => + case sig::KILL => return "SIGKILL"; - case SIGUSR1 => + case sig::USR1 => return "SIGUSR1"; - case SIGSEGV => + case sig::SEGV => return "SIGSEGV"; - case SIGUSR2 => + case sig::USR2 => return "SIGUSR2"; - case SIGPIPE => + case sig::PIPE => return "SIGPIPE"; - case SIGALRM => + case sig::ALRM => return "SIGALRM"; - case SIGTERM => + case sig::TERM => return "SIGTERM"; - case SIGCHLD => + case sig::CHLD => return "SIGCHLD"; - case SIGCONT => + case sig::CONT => return "SIGCONT"; - case SIGSTOP => + case sig::STOP => return "SIGSTOP"; - case SIGTSTP => + case sig::TSTP => return "SIGTSTP"; - case SIGTTIN => + case sig::TTIN => return "SIGTTIN"; - case SIGTTOU => + case sig::TTOU => return "SIGTTOU"; - case SIGURG => + case sig::URG => return "SIGURG"; - case SIGXCPU => + case sig::XCPU => return "SIGXCPU"; - case SIGXFSZ => + case sig::XFSZ => return "SIGXFSZ"; - case SIGVTALRM => + case sig::VTALRM => return "SIGVTALRM"; - case SIGPROF => + case sig::PROF => return "SIGPROF"; - case SIGWINCH => + case sig::WINCH => return "SIGWINCH"; - case SIGIO => + case sig::IO => return "SIGIO"; - case SIGPOLL => + case sig::POLL => return "SIGPOLL"; - case SIGPWR => + case sig::PWR => return "SIGPWR"; - case SIGSYS => + case sig::SYS => return "SIGSYS"; case => abort(); // unreachable }; diff --git a/unix/signal/types.ha b/unix/signal/types.ha @@ -5,4 +5,4 @@ // which was caught, the second provides information about the signal, and the // third argument is the ucontext, which is usually ignored by most signal // handlers. -export type handler = fn(sig: int, info: *siginfo, ucontext: *void) void; +export type handler = fn(sig: sig, info: *siginfo, ucontext: *void) void;