Files
Odin/core/sys/posix/signal.odin
Harold Brenes 219b0fe535 Replace system:System.framework imports with system:System
This makes the linker work for both macOS and iOS targets
2025-07-13 15:45:21 -04:00

1336 lines
34 KiB
Odin

#+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix
import "base:intrinsics"
import "core:c"
when ODIN_OS == .Darwin {
foreign import lib "system:System"
} else {
foreign import lib "system:c"
}
// signal.h - signals
foreign lib {
/*
Raise a signal to the process/group specified by pid.
If sig is 0, this function can be used to check if the pid is just checked for validity.
If pid is -1, the signal is sent to all processes that the current process has permission to send.
If pid is negative (not -1), the signal is sent to all processes in the group identifier by the
absolute value.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html ]]
*/
kill :: proc(pid: pid_t, sig: Signal) -> result ---
/*
Shorthand for `kill(-pgrp, sig)` which will kill all processes in the given process group.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html ]]
*/
killpg :: proc(pgrp: pid_t, sig: Signal) -> result ---
/*
Writes a language-dependent message to stderror.
Example:
posix.psignal(.SIGSEGV, "that didn't go well")
Possible Output:
that didn't go well: Segmentation fault
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/psignal.html ]]
*/
psignal :: proc(signum: Signal, message: cstring) ---
/*
Send a signal to a thread.
As with kill, if sig is 0, only validation (of the pthread_t given) is done and no signal is sent.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html ]]
*/
pthread_kill :: proc(thread: pthread_t, sig: Signal) -> Errno ---
/*
Examine and change blocked signals.
Equivalent to sigprocmask(), without the restriction that the call be made in a single-threaded process.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html ]]
*/
pthread_sigmask :: proc(how: Sig, set: ^sigset_t, oset: ^sigset_t) -> Errno ---
/*
Examine and change blocked signals in a single-threaded process.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html ]]
*/
@(link_name=LSIGPROCMASK)
sigprocmask :: proc(how: Sig, set: ^sigset_t, oldset: ^sigset_t) -> result ---
/*
Examine and change a signal action.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaction.html ]]
*/
@(link_name=LSIGACTION)
sigaction :: proc(sig: Signal, act: ^sigaction_t, oact: ^sigaction_t) -> result ---
@(link_name=LSIGADDSET)
sigaddset :: proc(set: ^sigset_t, signo: Signal) -> result ---
@(link_name=LSIGDELSET)
sigdelset :: proc(^sigset_t, Signal) -> c.int ---
@(link_name=LSIGEMPTYSET)
sigemptyset :: proc(^sigset_t) -> c.int ---
@(link_name=LSIGFILLSET)
sigfillset :: proc(^sigset_t) -> c.int ---
/*
Set and get the signal alternate stack context.
Example:
sigstk := posix.stack_t {
ss_sp = make([^]byte, posix.SIGSTKSZ) or_else panic("allocation failure"),
ss_size = posix.SIGSTKSZ,
ss_flags = {},
}
if posix.sigaltstack(&sigstk, nil) != .OK {
fmt.panicf("sigaltstack failure: %v", posix.strerror(posix.errno()))
}
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaltstack.html ]]
*/
@(link_name=LSIGALTSTACK)
sigaltstack :: proc(ss: ^stack_t, oss: ^stack_t) -> result ---
/*
Adds sig to the signal mask of the calling process.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]]
*/
sighold :: proc(sig: Signal) -> result ---
/*
Sets the disposition of sig to SIG_IGN.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]]
*/
sigignore :: proc(sig: Signal) -> result ---
/*
Removes sig from the signal mask of the calling process and suspend the calling process until
a signal is received.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]]
*/
sigpause :: proc(sig: Signal) -> result ---
/*
Removes sig from the signal mask of the calling process.
Returns: always -1.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]]
*/
sigrelse :: proc(sig: Signal) -> result ---
/*
Changes the restart behavior when a function is interrupted by the specified signal.
If flag is true, SA_RESTART is removed, added otherwise.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/siginterrupt.html ]]
*/
siginterrupt :: proc(sig: Signal, flag: b32) -> result ---
/*
Test for a signal in a signal set.
Returns: 1 if it is a member, 0 if not, -1 (setting errno) on failure
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigismember.html ]]
*/
@(link_name=LSIGISMEMBER)
sigismember :: proc(set: ^sigset_t, signo: Signal) -> c.int ---
/*
Stores the set of signals that are blocked from delivery to the calling thread and that are pending
on the process or the calling thread.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html ]]
*/
@(link_name=LSIGPENDING)
sigpending :: proc(set: ^sigset_t) -> result ---
/*
Wait for one of the given signals.
Returns: always -1
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html ]]
*/
@(link_name=LSIGSUSPEND)
sigsuspend :: proc(sigmask: ^sigset_t) -> result ---
/*
Wait for queued signals.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigwait.html ]]
*/
sigwait :: proc(set: ^sigset_t, sig: ^Signal) -> Errno ---
/* NOTE: unimplemented on darwin.
void psiginfo(const siginfo_t *, const char *);
int sigqueue(pid_t, int, union sigval);
void (*sigset(int, void (*)(int)))(int);
int sigsuspend(const sigset_t *);
int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict,
const struct timespec *restrict);
int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
*/
}
sigval :: struct #raw_union {
sigval_int: c.int, /* [PSX] integer signal value */
sigval_ptr: rawptr, /* [PSX] pointer signal value */
}
ILL_Code :: enum c.int {
// Illegal opcode.
ILLOPC = ILL_ILLOPC,
// Illegal operand.
ILLOPN = ILL_ILLOPN,
// Illegal addressing mode.
ILLADR = ILL_ILLADR,
// Illegal trap.
ILLTRP = ILL_ILLTRP,
// Priviledged opcode.
PRVOPC = ILL_PRVOPC,
// Priviledged register.
PRVREG = ILL_PRVREG,
// Coprocessor error.
COPROC = ILL_COPROC,
// Internal stack error.
BADSTK = ILL_BADSTK,
}
FPE_Code :: enum c.int {
// Integer divide by zero.
INTDIV = FPE_INTDIV,
// Integer overflow.
INTOVF = FPE_INTOVF,
// Floating-point divide by zero.
FLTDIV = FPE_FLTDIV,
// Floating-point overflow.
FLTOVF = FPE_FLTOVF,
// Floating-point underflow.
FLTUND = FPE_FLTUND,
// Floating-point inexact result.
FLTRES = FPE_FLTRES,
// Invalid floating-point operation.
FLTINV = FPE_FLTINV,
// Subscript out of range.
FLTSUB = FPE_FLTSUB,
}
SEGV_Code :: enum c.int {
// Address not mapped to object.
MAPERR = SEGV_MAPERR,
// Invalid permissions for mapped object.
ACCERR = SEGV_ACCERR,
}
BUS_Code :: enum c.int {
// Invalid address alignment.
ADRALN = BUS_ADRALN,
// Nonexistent physical address.
ADRERR = BUS_ADRERR,
// Object-specific hardware error.
OBJERR = BUS_OBJERR,
}
TRAP_Code :: enum c.int {
// Process breakpoint.
BRKPT = TRAP_BRKPT,
// Process trace trap.
TRACE = TRAP_TRACE,
}
CLD_Code :: enum c.int {
// Child has exited..
EXITED = CLD_EXITED,
// Child has terminated abnormally and did not create a core file.
KILLED = CLD_KILLED,
// Child has terminated abnormally and created a core file.
DUMPED = CLD_DUMPED,
// Traced child trapped.
TRAPPED = CLD_TRAPPED,
// Child has stopped.
STOPPED = CLD_STOPPED,
// Stopped child has continued.
CONTINUED = CLD_CONTINUED,
}
POLL_Code :: enum c.int {
// Data input is available.
IN = POLL_IN,
// Output buffers available.
OUT = POLL_OUT,
// Input message available.
MSG = POLL_MSG,
// I/O error.
ERR = POLL_ERR,
// High priority input available.
PRI = POLL_PRI,
// Device disconnected.
HUP = POLL_HUP,
}
Any_Code :: enum c.int {
// Signal sent by kill().
USER = SI_USER,
// Signal sent by sigqueue().
QUEUE = SI_QUEUE,
// Signal generated by expiration of a timer set by timer_settime().
TIMER = SI_TIMER,
// Signal generated by completion of an asynchronous I/O request.
ASYNCIO = SI_ASYNCIO,
// Signal generated by arrival of a message on an empty message queue.
MESGQ = SI_MESGQ,
}
SA_Flags_Bits :: enum c.int {
// Do not generate SIGCHLD when children stop or stopped children continue.
NOCLDSTOP = log2(SA_NOCLDSTOP),
// Cause signal delivery to occur on an alternate stack.
ONSTACK = log2(SA_ONSTACK),
// Cause signal disposition to be set to SIG_DFL on entry to signal handlers.
RESETHAND = log2(SA_RESETHAND),
// Cause certain functions to become restartable.
RESTART = log2(SA_RESTART),
// Cause extra information to be passed to signal handlers at the time of receipt of a signal.
SIGINFO = log2(SA_SIGINFO),
// Cause implementation not to create zombie processes or status information on child termination.
NOCLDWAIT = log2(SA_NOCLDWAIT),
// Cause signal not to be automatically blocked on entry to signal handler.
SA_NODEFER = log2(SA_NODEFER),
}
SA_Flags :: bit_set[SA_Flags_Bits; c.int]
SS_Flag_Bits :: enum c.int {
// Process is executing on an alternate signal stack.
ONSTACK = log2(SS_ONSTACK),
// Alternate signal stack is disabled.
DISABLE = log2(SS_DISABLE),
}
SS_Flags :: bit_set[SS_Flag_Bits; c.int]
Sig :: enum c.int {
// Resulting set is the union of the current set and the signal set and the complement of
// the signal set pointed to by the argument.
BLOCK = SIG_BLOCK,
// Resulting set is the intersection of the current set and the complement of the signal set
// pointed to by the argument.
UNBLOCK = SIG_UNBLOCK,
// Resulting set is the signal set pointed to by the argument.
SETMASK = SIG_SETMASK,
}
when ODIN_OS == .NetBSD {
@(private) LSIGPROCMASK :: "__sigprocmask14"
@(private) LSIGACTION :: "__sigaction_siginfo"
@(private) LSIGADDSET :: "__sigaddset14"
@(private) LSIGDELSET :: "__sigdelset14"
@(private) LSIGEMPTYSET :: "__sigemptyset14"
@(private) LSIGFILLSET :: "__sigfillset14"
@(private) LSIGALTSTACK :: "__sigaltstack14"
@(private) LSIGISMEMBER :: "__sigismember14"
@(private) LSIGPENDING :: "__sigpending14"
@(private) LSIGSUSPEND :: "__sigsuspend14"
} else {
@(private) LSIGPROCMASK :: "sigprocmask"
@(private) LSIGACTION :: "sigaction"
@(private) LSIGADDSET :: "sigaddset"
@(private) LSIGDELSET :: "sigdelset"
@(private) LSIGEMPTYSET :: "sigemptyset"
@(private) LSIGFILLSET :: "sigfillset"
@(private) LSIGALTSTACK :: "sigaltstack"
@(private) LSIGISMEMBER :: "sigismember"
@(private) LSIGPENDING :: "sigpending"
@(private) LSIGSUSPEND :: "sigsuspend"
}
when ODIN_OS == .Darwin {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(5))
uid_t :: distinct c.uint32_t
sigset_t :: distinct c.uint32_t
SIGHUP :: 1
SIGQUIT :: 3
SIGTRAP :: 5
SIGPOLL :: 7
SIGKILL :: 9
SIGBUS :: 10
SIGSYS :: 12
SIGPIPE :: 13
SIGALRM :: 14
SIGURG :: 16
SIGCONT :: 19
SIGSTOP :: 17
SIGTSTP :: 18
SIGCHLD :: 20
SIGTTIN :: 21
SIGTTOU :: 22
SIGXCPU :: 24
SIGXFSZ :: 25
SIGVTALRM :: 26
SIGPROF :: 27
SIGWINCH :: 28
SIGUSR1 :: 30
SIGUSR2 :: 31
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x0008
SA_ONSTACK :: 0x0001
SA_RESETHAND :: 0x0004
SA_RESTART :: 0x0002
SA_SIGINFO :: 0x0040
SA_NOCLDWAIT :: 0x0020
SA_NODEFER :: 0x0010
SS_ONSTACK :: 0x0001
SS_DISABLE :: 0x0004
MINSIGSTKSZ :: 32768
SIGSTKSZ :: 131072
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
siginfo_t :: struct {
si_signo: Signal, /* [PSX] signal number */
si_errno: Errno, /* [PSX] errno value associated with this signal */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_pid: pid_t, /* [PSX] sending process ID */
si_uid: uid_t, /* [PSX] real user ID of sending process */
si_status: c.int, /* [PSX] exit value or signal */
si_addr: rawptr, /* [PSX] address of faulting instruction */
si_value: sigval, /* [PSX] signal value */
si_band: c.long, /* [PSX] band event for SIGPOLL */
__pad: [7]c.ulong,
}
ILL_ILLOPC :: 1
ILL_ILLOPN :: 4
ILL_ILLADR :: 5
ILL_ILLTRP :: 2
ILL_PRVOPC :: 3
ILL_PRVREG :: 6
ILL_COPROC :: 7
ILL_BADSTK :: 8
FPE_INTDIV :: 7
FPE_INTOVF :: 8
FPE_FLTDIV :: 1
FPE_FLTOVF :: 2
FPE_FLTUND :: 3
FPE_FLTRES :: 4
FPE_FLTINV :: 5
FPE_FLTSUB :: 6
SEGV_MAPERR :: 1
SEGV_ACCERR :: 2
BUS_ADRALN :: 1
BUS_ADRERR :: 2
BUS_OBJERR :: 3
TRAP_BRKPT :: 1
TRAP_TRACE :: 2
CLD_EXITED :: 1
CLD_KILLED :: 2
CLD_DUMPED :: 3
CLD_TRAPPED :: 4
CLD_STOPPED :: 5
CLD_CONTINUED :: 6
POLL_IN :: 1
POLL_OUT :: 2
POLL_MSG :: 3
POLL_ERR :: 4
POLL_PRI :: 5
POLL_HUP :: 6
SI_USER :: 0x10001
SI_QUEUE :: 0x10002
SI_TIMER :: 0x10003
SI_ASYNCIO :: 0x10004
SI_MESGQ :: 0x10005
} else when ODIN_OS == .FreeBSD {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(3))
uid_t :: distinct c.uint32_t
sigset_t :: struct {
__bits: [4]c.uint32_t,
}
SIGHUP :: 1
SIGQUIT :: 3
SIGTRAP :: 5
SIGPOLL :: 7
SIGKILL :: 9
SIGBUS :: 10
SIGSYS :: 12
SIGPIPE :: 13
SIGALRM :: 14
SIGURG :: 16
SIGCONT :: 19
SIGSTOP :: 17
SIGTSTP :: 18
SIGCHLD :: 20
SIGTTIN :: 21
SIGTTOU :: 22
SIGXCPU :: 24
SIGXFSZ :: 25
SIGVTALRM :: 26
SIGPROF :: 27
SIGWINCH :: 28
SIGUSR1 :: 30
SIGUSR2 :: 31
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_flags: SA_Flags, /* [PSX] special flags */
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x0008
SA_ONSTACK :: 0x0001
SA_RESETHAND :: 0x0004
SA_RESTART :: 0x0002
SA_SIGINFO :: 0x0040
SA_NOCLDWAIT :: 0x0020
SA_NODEFER :: 0x0010
SS_ONSTACK :: 0x0001
SS_DISABLE :: 0x0004
when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 {
MINSIGSTKSZ :: 1024 * 4
} else when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
MINSIGSTKSZ :: 512 * 4
}
SIGSTKSZ :: MINSIGSTKSZ + 32768
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
siginfo_t :: struct {
si_signo: Signal, /* [PSX] signal number */
si_errno: Errno, /* [PSX] errno value associated with this signal */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_pid: pid_t, /* [PSX] sending process ID */
si_uid: uid_t, /* [PSX] real user ID of sending process */
si_status: c.int, /* [PSX] exit value or signal */
si_addr: rawptr, /* [PSX] address of faulting instruction */
si_value: sigval, /* [PSX] signal value */
using _reason: struct #raw_union {
_fault: struct {
_trapno: c.int, /* machine specific trap code */
},
_timer: struct {
_timerid: c.int,
_overrun: c.int,
},
_mesgq: struct {
_mqd: c.int,
},
using _poll: struct {
si_band: c.long, /* [PSX] band event for SIGPOLL */
},
_capsicum: struct {
_syscall: c.int, /* syscall number for signals delivered as a result of system calls denied by capsicum */
},
__spare__: struct {
__spare1__: c.long,
__spare2__: [7]c.int,
},
},
}
ILL_ILLOPC :: 1
ILL_ILLOPN :: 2
ILL_ILLADR :: 3
ILL_ILLTRP :: 4
ILL_PRVOPC :: 5
ILL_PRVREG :: 6
ILL_COPROC :: 7
ILL_BADSTK :: 8
FPE_INTDIV :: 2
FPE_INTOVF :: 1
FPE_FLTDIV :: 3
FPE_FLTOVF :: 4
FPE_FLTUND :: 5
FPE_FLTRES :: 6
FPE_FLTINV :: 7
FPE_FLTSUB :: 8
SEGV_MAPERR :: 1
SEGV_ACCERR :: 2
BUS_ADRALN :: 1
BUS_ADRERR :: 2
BUS_OBJERR :: 3
TRAP_BRKPT :: 1
TRAP_TRACE :: 2
CLD_EXITED :: 1
CLD_KILLED :: 2
CLD_DUMPED :: 3
CLD_TRAPPED :: 4
CLD_STOPPED :: 5
CLD_CONTINUED :: 6
POLL_IN :: 1
POLL_OUT :: 2
POLL_MSG :: 3
POLL_ERR :: 4
POLL_PRI :: 5
POLL_HUP :: 6
SI_USER :: 0x10001
SI_QUEUE :: 0x10002
SI_TIMER :: 0x10003
SI_ASYNCIO :: 0x10004
SI_MESGQ :: 0x10005
} else when ODIN_OS == .NetBSD {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(3))
uid_t :: distinct c.uint32_t
sigset_t :: struct {
__bits: [4]c.uint32_t,
}
SIGHUP :: 1
SIGQUIT :: 3
SIGTRAP :: 5
SIGPOLL :: 7
SIGKILL :: 9
SIGBUS :: 10
SIGSYS :: 12
SIGPIPE :: 13
SIGALRM :: 14
SIGURG :: 16
SIGCONT :: 19
SIGSTOP :: 17
SIGTSTP :: 18
SIGCHLD :: 20
SIGTTIN :: 21
SIGTTOU :: 22
SIGXCPU :: 24
SIGXFSZ :: 25
SIGVTALRM :: 26
SIGPROF :: 27
SIGWINCH :: 28
SIGUSR1 :: 30
SIGUSR2 :: 31
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x0008
SA_ONSTACK :: 0x0001
SA_RESETHAND :: 0x0004
SA_RESTART :: 0x0002
SA_SIGINFO :: 0x0040
SA_NOCLDWAIT :: 0x0020
SA_NODEFER :: 0x0010
SS_ONSTACK :: 0x0001
SS_DISABLE :: 0x0004
MINSIGSTKSZ :: 8192
SIGSTKSZ :: MINSIGSTKSZ + 32768
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
@(private)
lwpid_t :: c.int32_t
siginfo_t :: struct #raw_union {
si_pad: [128]byte,
using _info: struct {
si_signo: Signal, /* [PSX] signal number */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_errno: Errno, /* [PSX] errno value associated with this signal */
// #ifdef _LP64
/* In _LP64 the union starts on an 8-byte boundary. */
_pad: c.int,
// #endif
using _reason: struct #raw_union {
using _rt: struct {
_pid: pid_t,
_uid: uid_t,
si_value: sigval, /* [PSX] signal value */
},
using _child: struct {
si_pid: pid_t, /* [PSX] sending process ID */
si_uid: uid_t, /* [PSX] real user ID of sending process */
si_status: c.int, /* [PSX] exit value or signal */
_utime: clock_t,
_stime: clock_t,
},
using _fault: struct {
si_addr: rawptr, /* [PSX] address of faulting instruction */
_trap: c.int,
_trap2: c.int,
_trap3: c.int,
},
using _poll: struct {
si_band: c.long, /* [PSX] band event for SIGPOLL */
_fd: FD,
},
_syscall: struct {
_sysnum: c.int,
_retval: [2]c.int,
_error: c.int,
_args: [8]c.uint64_t,
},
_ptrace_state: struct {
_pe_report_event: c.int,
_option: struct #raw_union {
_pe_other_pid: pid_t,
_pe_lwp: lwpid_t,
},
},
},
},
}
ILL_ILLOPC :: 1
ILL_ILLOPN :: 2
ILL_ILLADR :: 3
ILL_ILLTRP :: 4
ILL_PRVOPC :: 5
ILL_PRVREG :: 6
ILL_COPROC :: 7
ILL_BADSTK :: 8
FPE_INTDIV :: 1
FPE_INTOVF :: 2
FPE_FLTDIV :: 3
FPE_FLTOVF :: 4
FPE_FLTUND :: 5
FPE_FLTRES :: 6
FPE_FLTINV :: 7
FPE_FLTSUB :: 8
SEGV_MAPERR :: 1
SEGV_ACCERR :: 2
BUS_ADRALN :: 1
BUS_ADRERR :: 2
BUS_OBJERR :: 3
TRAP_BRKPT :: 1
TRAP_TRACE :: 2
CLD_EXITED :: 1
CLD_KILLED :: 2
CLD_DUMPED :: 3
CLD_TRAPPED :: 4
CLD_STOPPED :: 5
CLD_CONTINUED :: 6
POLL_IN :: 1
POLL_OUT :: 2
POLL_MSG :: 3
POLL_ERR :: 4
POLL_PRI :: 5
POLL_HUP :: 6
SI_USER :: 0
SI_QUEUE :: -1
SI_TIMER :: -2
SI_ASYNCIO :: -3
SI_MESGQ :: -4
} else when ODIN_OS == .OpenBSD {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(3))
uid_t :: distinct c.uint32_t
sigset_t :: distinct c.uint32_t
SIGHUP :: 1
SIGQUIT :: 3
SIGTRAP :: 5
SIGPOLL :: 7
SIGKILL :: 9
SIGBUS :: 10
SIGSYS :: 12
SIGPIPE :: 13
SIGALRM :: 14
SIGURG :: 16
SIGCONT :: 19
SIGSTOP :: 17
SIGTSTP :: 18
SIGCHLD :: 20
SIGTTIN :: 21
SIGTTOU :: 22
SIGXCPU :: 24
SIGXFSZ :: 25
SIGVTALRM :: 26
SIGPROF :: 27
SIGWINCH :: 28
SIGUSR1 :: 30
SIGUSR2 :: 31
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x0008
SA_ONSTACK :: 0x0001
SA_RESETHAND :: 0x0004
SA_RESTART :: 0x0002
SA_SIGINFO :: 0x0040
SA_NOCLDWAIT :: 0x0020
SA_NODEFER :: 0x0010
SS_ONSTACK :: 0x0001
SS_DISABLE :: 0x0004
MINSIGSTKSZ :: 3 << 12
SIGSTKSZ :: MINSIGSTKSZ + (1 << 12) * 4
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
SI_MAXSZ :: 128
SI_PAD :: (SI_MAXSZ / size_of(c.int)) - 3
siginfo_t :: struct {
si_signo: Signal, /* [PSX] signal number */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_errno: Errno, /* [PSX] errno value associated with this signal */
using _data: struct #raw_union {
_pad: [SI_PAD]c.int,
using _proc: struct {
si_pid: pid_t, /* [PSX] sending process ID */
si_uid: uid_t, /* [PSX] real user ID of sending process */
using _pdata: struct #raw_union {
using _kill: struct {
si_value: sigval,
},
using _cld: struct {
_utime: clock_t,
_stime: clock_t,
si_status: c.int,
},
},
},
using _fault: struct {
si_addr: rawptr,
_trapno: c.int,
},
using _file: struct {
_fd: FD,
si_band: c.long, /* [PSX] band event for SIGPOLL */
},
},
}
ILL_ILLOPC :: 1
ILL_ILLOPN :: 2
ILL_ILLADR :: 3
ILL_ILLTRP :: 4
ILL_PRVOPC :: 5
ILL_PRVREG :: 6
ILL_COPROC :: 7
ILL_BADSTK :: 8
FPE_INTDIV :: 1
FPE_INTOVF :: 2
FPE_FLTDIV :: 3
FPE_FLTOVF :: 4
FPE_FLTUND :: 5
FPE_FLTRES :: 6
FPE_FLTINV :: 7
FPE_FLTSUB :: 8
SEGV_MAPERR :: 1
SEGV_ACCERR :: 2
BUS_ADRALN :: 1
BUS_ADRERR :: 2
BUS_OBJERR :: 3
TRAP_BRKPT :: 1
TRAP_TRACE :: 2
CLD_EXITED :: 1
CLD_KILLED :: 2
CLD_DUMPED :: 3
CLD_TRAPPED :: 4
CLD_STOPPED :: 5
CLD_CONTINUED :: 6
POLL_IN :: 1
POLL_OUT :: 2
POLL_MSG :: 3
POLL_ERR :: 4
POLL_PRI :: 5
POLL_HUP :: 6
SI_USER :: 0
SI_QUEUE :: -2
SI_TIMER :: -3
SI_ASYNCIO :: -4 // NOTE: not implemented
SI_MESGQ :: -5 // NOTE: not implemented
} else when ODIN_OS == .Linux {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(2))
uid_t :: distinct c.uint32_t
sigset_t :: struct {
__val: [1024/(8 * size_of(c.ulong))]c.ulong,
}
SIGHUP :: 1
SIGQUIT :: 3
SIGTRAP :: 5
SIGBUS :: 7
SIGKILL :: 9
SIGUSR1 :: 10
SIGUSR2 :: 12
SIGPIPE :: 13
SIGALRM :: 14
SIGCHLD :: 17
SIGCONT :: 18
SIGSTOP :: 19
SIGTSTP :: 20
SIGTTIN :: 21
SIGTTOU :: 22
SIGURG :: 23
SIGXCPU :: 24
SIGXFSZ :: 25
SIGVTALRM :: 26
SIGPROF :: 27
SIGWINCH :: 28
SIGPOLL :: 29
SIGSYS :: 31
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
sa_restorer: proc "c" (),
}
SIG_BLOCK :: 0
SIG_UNBLOCK :: 1
SIG_SETMASK :: 2
SA_NOCLDSTOP :: 1
SA_NOCLDWAIT :: 2
SA_SIGINFO :: 4
SA_ONSTACK :: 0x08000000
SA_RESTART :: 0x10000000
SA_NODEFER :: 0x40000000
SA_RESETHAND :: 0x80000000
SS_ONSTACK :: 1
SS_DISABLE :: 2
when ODIN_ARCH == .arm64 {
MINSIGSTKSZ :: 6144
SIGSTKSZ :: 12288
} else {
MINSIGSTKSZ :: 2048
SIGSTKSZ :: 8192
}
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_flags: SS_Flags, /* [PSX] flags */
ss_size: c.size_t, /* [PSX] stack size */
}
@(private)
__SI_MAX_SIZE :: 128
when size_of(int) == 8 {
@(private)
_pad0 :: struct {
_pad0: c.int,
}
@(private)
__SI_PAD_SIZE :: (__SI_MAX_SIZE / size_of(c.int)) - 4
} else {
@(private)
_pad0 :: struct {}
@(private)
__SI_PAD_SIZE :: (__SI_MAX_SIZE / size_of(c.int)) - 3
}
siginfo_t :: struct #align(8) {
si_signo: Signal, /* [PSX] signal number */
si_errno: Errno, /* [PSX] errno value associated with this signal */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
__pad0: _pad0,
using _sifields: struct #raw_union {
_pad: [__SI_PAD_SIZE]c.int,
using _: struct {
si_pid: pid_t, /* [PSX] sending process ID */
si_uid: uid_t, /* [PSX] real user ID of sending process */
using _: struct #raw_union {
si_status: c.int, /* [PSX] exit value or signal */
si_value: sigval, /* [PSX] signal value */
},
},
using _: struct {
si_addr: rawptr, /* [PSX] address of faulting instruction */
},
using _: struct {
si_band: c.long, /* [PSX] band event for SIGPOLL */
},
},
}
ILL_ILLOPC :: 1
ILL_ILLOPN :: 2
ILL_ILLADR :: 3
ILL_ILLTRP :: 4
ILL_PRVOPC :: 5
ILL_PRVREG :: 6
ILL_COPROC :: 7
ILL_BADSTK :: 8
FPE_INTDIV :: 1
FPE_INTOVF :: 2
FPE_FLTDIV :: 3
FPE_FLTOVF :: 4
FPE_FLTUND :: 5
FPE_FLTRES :: 6
FPE_FLTINV :: 7
FPE_FLTSUB :: 8
SEGV_MAPERR :: 1
SEGV_ACCERR :: 2
BUS_ADRALN :: 1
BUS_ADRERR :: 2
BUS_OBJERR :: 3
TRAP_BRKPT :: 1
TRAP_TRACE :: 2
CLD_EXITED :: 1
CLD_KILLED :: 2
CLD_DUMPED :: 3
CLD_TRAPPED :: 4
CLD_STOPPED :: 5
CLD_CONTINUED :: 6
POLL_IN :: 1
POLL_OUT :: 2
POLL_MSG :: 3
POLL_ERR :: 4
POLL_PRI :: 5
POLL_HUP :: 6
SI_USER :: 0
SI_QUEUE :: -1
SI_TIMER :: -2
SI_MESGQ :: -3
SI_ASYNCIO :: -4
} else when ODIN_OS == .Haiku {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(3))
uid_t :: distinct c.uint32_t
sigset_t :: distinct u64
SIGHUP :: 1 // hangup -- tty is gone!
//SIGINT :: 2 // interrupt
SIGQUIT :: 3 // `quit' special character typed in tty
//SIGILL :: 4 // illegal instruction
SIGCHLD :: 5 // child process exited
//SIGABRT :: 6 // abort() called, dont' catch
SIGPIPE :: 7 // write to a pipe w/no readers
//SIGFPE :: 8 // floating point exception
SIGKILL :: 9 // kill a team (not catchable)
SIGSTOP :: 10 // suspend a thread (not catchable)
//SIGSEGV :: 11 // segmentation violation (read: invalid pointer)
SIGCONT :: 12 // continue execution if suspended
SIGTSTP :: 13 // `stop' special character typed in tty
SIGALRM :: 14 // an alarm has gone off (see alarm())
//SIGTERM :: 15 // termination requested
SIGTTIN :: 16 // read of tty from bg process
SIGTTOU :: 17 // write to tty from bg process
SIGUSR1 :: 18 // app defined signal 1
SIGUSR2 :: 19 // app defined signal 2
SIGWINCH :: 20 // tty window size changed
SIGKILLTHR :: 21 // be specific: kill just the thread, not team
SIGTRAP :: 22 // Trace/breakpoint trap
SIGPOLL :: 23 // Pollable event
SIGPROF :: 24 // Profiling timer expired
SIGSYS :: 25 // Bad system call
SIGURG :: 26 // High bandwidth data is available at socket
SIGVTALRM :: 27 // Virtual timer expired
SIGXCPU :: 28 // CPU time limit exceeded
SIGXFSZ :: 29 // File size limit exceeded
SIGBUS :: 30 // access to undefined portion of a memory object
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
sa_userdata: rawptr, /* will be passed to the signal handler, BeOS extension */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x01
SA_NOCLDWAIT :: 0x02
SA_RESETHAND :: 0x04
SA_NODEFER :: 0x08
SA_RESTART :: 0x10
SA_ONSTACK :: 0x20
SA_SIGINFO :: 0x40
SS_ONSTACK :: 1
SS_DISABLE :: 2
MINSIGSTKSZ :: 8192
SIGSTKSZ :: 16384
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
siginfo_t :: struct {
si_signo: Signal, /* [PSX] signal number */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_errno: Errno, /* [PSX] errno value associated with this signal */
si_pid: pid_t, /* sending process ID */
si_uid: uid_t, /* real user ID of sending process */
si_addr: rawptr, /* address of faulting instruction */
si_status: c.int, /* exit value or signal */
si_band: c.long, /* band event for SIGPOLL */
si_value: sigval, /* signal value */
}
/* any signal */
SI_USER :: 0 /* signal sent by user */
SI_QUEUE :: 1 /* signal sent by sigqueue() */
SI_TIMER :: 2 /* signal sent on timer_settime() timeout */
SI_ASYNCIO :: 3 /* signal sent on asynchronous I/O completion */
SI_MESGQ :: 4 /* signal sent on arrival of message on empty message queue */
/* SIGILL */
ILL_ILLOPC :: 10 /* illegal opcode */
ILL_ILLOPN :: 11 /* illegal operand */
ILL_ILLADR :: 12 /* illegal addressing mode */
ILL_ILLTRP :: 13 /* illegal trap */
ILL_PRVOPC :: 14 /* privileged opcode */
ILL_PRVREG :: 15 /* privileged register */
ILL_COPROC :: 16 /* coprocessor error */
ILL_BADSTK :: 17 /* internal stack error */
/* SIGFPE */
FPE_INTDIV :: 20 /* integer division by zero */
FPE_INTOVF :: 21 /* integer overflow */
FPE_FLTDIV :: 22 /* floating-point division by zero */
FPE_FLTOVF :: 23 /* floating-point overflow */
FPE_FLTUND :: 24 /* floating-point underflow */
FPE_FLTRES :: 25 /* floating-point inexact result */
FPE_FLTINV :: 26 /* invalid floating-point operation */
FPE_FLTSUB :: 27 /* subscript out of range */
/* SIGSEGV */
SEGV_MAPERR :: 30 /* address not mapped to object */
SEGV_ACCERR :: 31 /* invalid permissions for mapped object */
/* SIGBUS */
BUS_ADRALN :: 40 /* invalid address alignment */
BUS_ADRERR :: 41 /* nonexistent physical address */
BUS_OBJERR :: 42 /* object-specific hardware error */
/* SIGTRAP */
TRAP_BRKPT :: 50 /* process breakpoint */
TRAP_TRACE :: 51 /* process trace trap. */
/* SIGCHLD */
CLD_EXITED :: 60 /* child exited */
CLD_KILLED :: 61 /* child terminated abnormally without core dump */
CLD_DUMPED :: 62 /* child terminated abnormally with core dump */
CLD_TRAPPED :: 63 /* traced child trapped */
CLD_STOPPED :: 64 /* child stopped */
CLD_CONTINUED :: 65 /* stopped child continued */
/* SIGPOLL */
POLL_IN :: 70 /* input available */
POLL_OUT :: 71 /* output available */
POLL_MSG :: 72 /* input message available */
POLL_ERR :: 73 /* I/O error */
POLL_PRI :: 74 /* high priority input available */
POLL_HUP :: 75 /* device disconnected */
}