hare

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

commit db5d7fa965245a2791a0f2a1391040f002d5083c
parent e2945c26c09fde2545bc91e9c35a908fa18a03ff
Author: Mykyta Holubakha <hilobakho@gmail.com>
Date:   Sat, 13 Mar 2021 18:32:59 +0200

rt: implement sigaction for signal handling

Added complete siginfo struct definition with necessary types.

Always use SA_RESTORER and add a restorer (copied over from musl), as not
providing a restorer (which is done by libc implicitly in C code) causes
segfaults on signal receipt.

Implemented restorers for amd64 and aarch64

Diffstat:
Art/+aarch64/restore.s | 11+++++++++++
Mrt/+linux/syscalls.ha | 17+++++++++++++++++
Mrt/+linux/types.ha | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+x86_64/restore.s | 11+++++++++++
4 files changed, 166 insertions(+), 0 deletions(-)

diff --git a/rt/+aarch64/restore.s b/rt/+aarch64/restore.s @@ -0,0 +1,11 @@ +// Copied from musl + +.global rt.restore +.global rt.restore_si +.type rt.restore,@function +.type rt.restore_si,@function +rt.restore: +rt.restore_si: + mov x8,#139 + svc 0 + diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha @@ -344,3 +344,20 @@ export fn sigprocmask( how: u64, set: uintptr: u64, old: uintptr: u64, size(sigset): u64))?: int; }; + +fn restore() void; +fn restore_si() void; + +export fn sigaction( + signum: int, + act: *const sigact, + old: nullable *sigact +) (int | errno) = { + let real_act = *act; + real_act.sa_flags |= SA_RESTORER; + let restore_fn = if ((act.sa_flags & SA_SIGINFO) != 0) &restore_si else &restore; + real_act.sa_restorer = &restore; + return wrap_return(syscall4(SYS_rt_sigaction, + signum: u64, &real_act: uintptr: u64, old: uintptr: u64, + size(sigset): u64))?: int; +}; diff --git a/rt/+linux/types.ha b/rt/+linux/types.ha @@ -8,6 +8,12 @@ export type gid_t = uint; export type time_t = i64; export type suseconds_t = i64; export type nfds_t = u64; +export type pid_t = int; +export type timer_t = int; +export type clock_t = i64; +export type si_band_t = i64; + +export def NSIG: int = 64; export type sigset = struct { __val: [1]u64, @@ -331,6 +337,127 @@ export type pollfd = struct { export def TFD_TIMER_ABSTIME: int = 1; export def TFD_TIMER_CANCEL_ON_SET: int = 2; +export def SIG_BLOCK: int = 0; +export def SIG_UNBLOCK: int = 1; +export def SIG_SETMASK: int = 2; + +def SI_MAX_SIZE: size = 128 / size(u8); + +export type sigval_t = union { + sival_t: int, + sival_ptr: *void, +}; + + +//#define __ADDR_BND_PKEY_PAD (__alignof__(void *) < sizeof(short) ? sizeof(short) : __alignof__(void *)) +def __ADDR_BND_PKEY_PAD: size = 8; + +export type siginfo = union { + struct { + si_signo: int, + si_errno: int, + si_code: int, + + union { + // kill() + struct { + si_pid: pid_t, + si_uid: u32, + }, + + // POSIX.1b timers + struct { + si_tid: timer_t, + si_overrun: int, + _sigval: sigval_t, // @ signals + si_sys_private: int, + }, + + // POSIX.1b signals + struct { + _sig_pid: pid_t, // @kill + _sig_uid: u32, // @ kill + union { + si_value: sigval_t, + si_int: int, + si_ptr: *void, + } + }, + + // SIGCHLD + struct { + _chld_pid: pid_t, // @ kill + _chld_uid: u32, // @ kill + si_status: int, + si_utime: clock_t, + si_stime: clock_t, + }, + + // SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT + struct { + si_addr: *void, + + union { + + // used when si_code=BUS_MCEERR_AR or + // used when si_code=BUS_MCEERR_AO + si_addr_lsb: i16, + + struct { + _dummy_bnd: [__ADDR_BND_PKEY_PAD]u8, + si_lower: *void, + si_upper: *void, + }, + + struct { + _dummy_pkey: [__ADDR_BND_PKEY_PAD]u8, + si_pkey: u32, + }, + }, + }, + + // SIGPOLL + struct { + si_band: si_band_t, + si_fd: int, + }, + + // SIGSYS + struct { + si_call_addr: *void, + si_syscall: int, + si_arch: uint, + }, + + }, + }, + _si_pad: [SI_MAX_SIZE - 3 * size(int)]u8, +}; + +export def SA_NOCLDSTOP: u64 = 0x00000001; +export def SA_NOCLDWAIT: u64 = 0x00000002; +export def SA_SIGINFO: u64 = 0x00000004; +export def SA_ONSTACK: u64 = 0x08000000; +export def SA_RESTART: u64 = 0x10000000; +export def SA_NODEFER: u64 = 0x40000000; +export def SA_RESETHAND: u64 = 0x80000000; +export def SA_NOMASK: u64 = SA_NODEFER; +export def SA_ONESHOT: u64 = SA_RESETHAND; +export def SA_RESTORER: u64 = 0x04000000; + +export type sigact = struct { + union { + sa_handler: *fn (int) void, + sa_sigaction: *fn (int, *siginfo, *void) void, + }, + sa_flags: u64, + sa_restorer: *fn () void, + sa_mask: sigset, +}; + +export def SFD_NONBLOCK: int = O_NONBLOCK; +export def SFD_CLOEXEC: int = O_CLOEXEC; + export type signalfd_siginfo = struct { ssi_signo: u32, ssi_errno: i32, diff --git a/rt/+x86_64/restore.s b/rt/+x86_64/restore.s @@ -0,0 +1,11 @@ +// Stolen from MUSL + +.global rt.restore +.global rt.restore_si +.type rt.restore,@function +.type rt.restore_si,@function +rt.restore: +rt.restore_si: + movl $15, %eax + syscall +