From a21922336d47f1ec58ba3b4fd3ce3afa67003633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Tue, 26 Jul 2022 13:22:24 +0200 Subject: [PATCH 01/35] Add /sbin/init based on suckless sinit. --- Makefile | 2 +- etc/Makefile | 5 ++- etc/rc.init | 13 ++++++ etc/rc.shutdown | 3 ++ include/signal.h | 8 ++++ include/sys/syscall.h | 3 +- include/sys/syscallargs.h | 8 ++++ lib/libc/sys/sigwait.c | 56 ++++++++++++++++++++++++ lib/libc/sys/syscalls.S | 1 + sbin/Makefile | 9 ++++ sbin/init/LICENSE | 21 +++++++++ sbin/init/Makefile | 6 +++ sbin/init/README | 26 +++++++++++ sbin/init/config.h | 5 +++ sbin/init/init.8 | 60 ++++++++++++++++++++++++++ sbin/init/init.c | 91 +++++++++++++++++++++++++++++++++++++++ sys/kern/main.c | 6 ++- sys/kern/syscalls.c | 5 +++ sys/kern/syscalls.master | 2 + sys/kern/sysent.h | 2 + 20 files changed, 327 insertions(+), 5 deletions(-) create mode 100755 etc/rc.init create mode 100755 etc/rc.shutdown create mode 100644 lib/libc/sys/sigwait.c create mode 100644 sbin/Makefile create mode 100644 sbin/init/LICENSE create mode 100644 sbin/init/Makefile create mode 100644 sbin/init/README create mode 100644 sbin/init/config.h create mode 100644 sbin/init/init.8 create mode 100644 sbin/init/init.c diff --git a/Makefile b/Makefile index f71e66ffda..d429c78ccb 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ TOPDIR = $(CURDIR) # Directories which require calling make recursively -SUBDIR = sys lib bin usr.bin etc include +SUBDIR = sys lib bin usr.bin sbin etc include all: install diff --git a/etc/Makefile b/etc/Makefile index 7e1a7c7681..f5c24a2687 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -2,7 +2,7 @@ TOPDIR = $(realpath ..) -FILES = group master.passwd .kshrc shells +FILES = group master.passwd rc.init rc.shutdown .kshrc shells INSTALL-FILES = $(addprefix $(SYSROOT)/etc/, $(FILES)) all: build @@ -12,3 +12,6 @@ include $(TOPDIR)/build/common.mk $(SYSROOT)/etc/%: % echo "[INSTALL] $(DIR)$* -> /etc/$*" $(INSTALL) -m 644 -D $< $@ + +install-here: + chmod 755 $(SYSROOT)/etc/rc.* diff --git a/etc/rc.init b/etc/rc.init new file mode 100755 index 0000000000..5ef891b160 --- /dev/null +++ b/etc/rc.init @@ -0,0 +1,13 @@ +#!/bin/ksh + +umask 022 + +echo " __ __ _ _ _ ____ _____ " +echo " | \/ (_) (_) | / __ \ / ____| " +echo " | \ / |_ _ __ ___ _| | _____ _ __| | | | (___ " +echo " | |\/| | | '_ \` _ \| | |/ / _ \ '__| | | |\___ \ " +echo " | | | | | | | | | | | < __/ | | |__| |____) | " +echo " |_| |_|_|_| |_| |_|_|_|\_\___|_| \____/|_____/ " +echo + +exec /bin/ksh diff --git a/etc/rc.shutdown b/etc/rc.shutdown new file mode 100755 index 0000000000..2652955025 --- /dev/null +++ b/etc/rc.shutdown @@ -0,0 +1,3 @@ +#!/bin/ksh + +echo "Shutdown not supported yet!" diff --git a/include/signal.h b/include/signal.h index fa5d84fcae..907dad28bb 100644 --- a/include/signal.h +++ b/include/signal.h @@ -35,6 +35,7 @@ #define _SIGNAL_H_ #include +#include #include __BEGIN_DECLS @@ -68,6 +69,13 @@ int sigsuspend(const sigset_t *); int killpg(int pgrp, int sig); int siginterrupt(int sig, int flag); +/* + * X/Open CAE Specification Issue 5; IEEE Std 1003.1b-1993 (POSIX) + */ +int sigwait(const sigset_t *__restrict, int *__restrict); +int sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info, + const struct timespec *__restrict timeout); + /* * Mimiker specific stuff. */ diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 70af2a5d63..94e3e21b18 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -91,6 +91,7 @@ #define SYS_fsync 83 #define SYS_kqueue1 84 #define SYS_kevent 85 -#define SYS_MAXSYSCALL 86 +#define SYS_sigtimedwait 86 +#define SYS_MAXSYSCALL 87 #define SYS_MAXSYSARGS 6 diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 28ad24bd10..89cd53a8af 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -8,6 +8,8 @@ #include #include #include +#include + #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } @@ -435,3 +437,9 @@ typedef struct { SYSCALLARG(size_t) nevents; SYSCALLARG(const struct timespec *) timeout; } kevent_args_t; + +typedef struct { + SYSCALLARG(const sigset_t *) set; + SYSCALLARG(siginfo_t *) info; + SYSCALLARG(struct timespec *) timeout; +} sigtimedwait_args_t; diff --git a/lib/libc/sys/sigwait.c b/lib/libc/sys/sigwait.c new file mode 100644 index 0000000000..408ba03767 --- /dev/null +++ b/lib/libc/sys/sigwait.c @@ -0,0 +1,56 @@ +/* $NetBSD: sigwait.c,v 1.5 2012/03/20 16:26:12 matt Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * This is wrapper around sigtimedwait(2), providing sigwait() + * implementation for userland. + */ +int +sigwait(const sigset_t * __restrict set, int * __restrict signum) +{ + int saved_errno, new_errno, sig; + + saved_errno = errno; + sig = sigtimedwait(set, NULL, NULL); + new_errno = errno; + errno = saved_errno; + if (sig < 0) + return (new_errno); + *signum = sig; + return (0); +} diff --git a/lib/libc/sys/syscalls.S b/lib/libc/sys/syscalls.S index bb1240f9a3..613f260ee1 100644 --- a/lib/libc/sys/syscalls.S +++ b/lib/libc/sys/syscalls.S @@ -82,3 +82,4 @@ SYSCALL(sync, SYS_sync) SYSCALL(fsync, SYS_fsync) SYSCALL(kqueue1, SYS_kqueue1) SYSCALL(kevent, SYS_kevent) +SYSCALL(sigtimedwait, SYS_sigtimedwait) diff --git a/sbin/Makefile b/sbin/Makefile new file mode 100644 index 0000000000..499be24f06 --- /dev/null +++ b/sbin/Makefile @@ -0,0 +1,9 @@ +# vim: tabstop=8 shiftwidth=8 noexpandtab: + +TOPDIR = $(realpath ..) + +SUBDIR = init + +all: build + +include $(TOPDIR)/build/common.mk diff --git a/sbin/init/LICENSE b/sbin/init/LICENSE new file mode 100644 index 0000000000..91b577935b --- /dev/null +++ b/sbin/init/LICENSE @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2014-2015 Dimitris Papastamos + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/sbin/init/Makefile b/sbin/init/Makefile new file mode 100644 index 0000000000..aaf2853bcc --- /dev/null +++ b/sbin/init/Makefile @@ -0,0 +1,6 @@ +TOPDIR = $(realpath ../..) + +PROGRAM = init +FORMAT-EXCLUDE = $(SOURCES) + +include $(TOPDIR)/build/build.prog.mk diff --git a/sbin/init/README b/sbin/init/README new file mode 100644 index 0000000000..13642b83a1 --- /dev/null +++ b/sbin/init/README @@ -0,0 +1,26 @@ +sinit - suckless init +===================== + +sinit is a simple init. It was initially based on +Rich Felker's minimal init[1]. + +Why? +---- + +I wanted to get rid of Busybox init on my toy distro[2]. + +How? +---- + +There are 3 signals that sinit will act on. + + SIGUSR1: powers off the machine. + SIGINT: reboots the machine (or alternatively via ctrl-alt-del). + SIGCHLD: reap children + +To see how sinit integrates with the init scripts, then have +a look at [3]. + +[1] https://gist.github.com/rofl0r/6168719 +[2] http://git.2f30.org/morpheus/ +[3] http://git.2f30.org/ports/tree/fs/ diff --git a/sbin/init/config.h b/sbin/init/config.h new file mode 100644 index 0000000000..3d2da6fcb6 --- /dev/null +++ b/sbin/init/config.h @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ + +static char *const rcinitcmd[] = { "/etc/rc.init", NULL }; +static char *const rcrebootcmd[] = { "/etc/rc.shutdown", "reboot", NULL }; +static char *const rcpoweroffcmd[] = { "/etc/rc.shutdown", "poweroff", NULL }; diff --git a/sbin/init/init.8 b/sbin/init/init.8 new file mode 100644 index 0000000000..605b457bd2 --- /dev/null +++ b/sbin/init/init.8 @@ -0,0 +1,60 @@ +.Dd December 4, 2014 +.Dt SINIT 8 sinit\-1.1 +.Os +.Sh NAME +.Nm sinit +.Nd simple init +.Sh DESCRIPTION +.Nm +is a simple init. It is configured by modifying +.Dq config.h +and recompiling the code. +.Ss Init sequence +By default +.Nm +will execute +.Dq /bin/rc.init . +You can chain your init scripts together at that point to allow for +single-user and multi-user operation. +.Ss Signal handling +.Nm +will respond to the following signals: +.Bl -tag -width xxxxxxxx +.It USR1 +Default action is to initiate the shutdown sequence by +executing +.Dq /bin/rc.shutdown poweroff . +.It INT +Default action is to initiate the reboot sequence by +executing +.Dq /bin/rc.shutdown reboot . +.It CHLD +Reap children. +.El +.Ss General considerations +Running the +.Dq rc.shutdown +script directly is not recommended. If any +process in your session has stale filesystem references then it is +likely your init scripts will fail to unmount the filesystem cleanly. +It is recommended to signal +.Nm +via a wrapper script. +.Pp +.Nm +does not clear utmp records. The version of +.Xr getty 8 +in ubase clears the utmp entries on the specified tty before it +spawns the given program, usually +.Xr login 1 . +.Pp +.Nm +does not restart +.Xr getty 8 +or interact with it in any way. You will need an external +respawning mechanism to restart it. +.Sh SEE ALSO +.Xr getty 8 , +.Xr killall5 8 +.Sh AUTHORS +.An Dimitris Papastamos Aq Mt sin@2f30.org . diff --git a/sbin/init/init.c b/sbin/init/init.c new file mode 100644 index 0000000000..716671087f --- /dev/null +++ b/sbin/init/init.c @@ -0,0 +1,91 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include +#include +#include +#include + +#define LEN(x) (sizeof (x) / sizeof *(x)) +#define TIMEO 30 + +static void sigpoweroff(void); +static void sigreap(void); +static void sigreboot(void); +static void spawn(char *const []); + +static struct { + int sig; + void (*handler)(void); +} sigmap[] = { + { SIGUSR1, sigpoweroff }, + { SIGCHLD, sigreap }, + { SIGALRM, sigreap }, + { SIGINT, sigreboot }, +}; + +#include "config.h" + +static sigset_t set; + +int +main(void) +{ + int sig; + size_t i; + + if (getpid() != 1) + return 1; + chdir("/"); + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, NULL); + spawn(rcinitcmd); + while (1) { + alarm(TIMEO); + sigwait(&set, &sig); + for (i = 0; i < LEN(sigmap); i++) { + if (sigmap[i].sig == sig) { + sigmap[i].handler(); + break; + } + } + } + /* not reachable */ + return 0; +} + +static void +sigpoweroff(void) +{ + spawn(rcpoweroffcmd); +} + +static void +sigreap(void) +{ + while (waitpid(-1, NULL, WNOHANG) > 0) + ; + alarm(TIMEO); +} + +static void +sigreboot(void) +{ + spawn(rcrebootcmd); +} + +static void +spawn(char *const argv[]) +{ + switch (fork()) { + case 0: + sigprocmask(SIG_UNBLOCK, &set, NULL); + setsid(); + execvp(argv[0], argv); + perror("execvp"); + _exit(1); + case -1: + perror("fork"); + } +} diff --git a/sys/kern/main.c b/sys/kern/main.c index 598cf199c3..7bf642bf5b 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -62,8 +62,10 @@ static __noreturn void start_init(__unused void *arg) { assert(_stderr == 2); char *init = kenv_get("init"); - if (init) - kern_execve(init, kenv_get_init(), (char *[]){NULL}); + if (init == NULL) + init = "/sbin/init"; + + kern_execve(init, kenv_get_init(), (char *[]){NULL}); char *test = kenv_get("test"); if (test) diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 0a4c58506a..08e7b5b499 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1311,3 +1311,8 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { kfree(M_TEMP, eventlist); return error; } + +static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, + register_t *res) { + return ENOTSUP; +} diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 6eaa152e38..7798c808f1 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -4,6 +4,7 @@ #include #include #include +#include #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } @@ -99,5 +100,6 @@ 83 { int sys_fsync(int fd); } 84 { int sys_kqueue1(int flags); } 85 { int sys_kevent(int kq, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); } +86 { int sys_sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); } ; vim: ts=4 sw=4 sts=4 et diff --git a/sys/kern/sysent.h b/sys/kern/sysent.h index d370e999be..430c7a0d7c 100644 --- a/sys/kern/sysent.h +++ b/sys/kern/sysent.h @@ -91,6 +91,7 @@ static int sys_sync(proc_t *, void *, register_t *); static int sys_fsync(proc_t *, fsync_args_t *, register_t *); static int sys_kqueue1(proc_t *, kqueue1_args_t *, register_t *); static int sys_kevent(proc_t *, kevent_args_t *, register_t *); +static int sys_sigtimedwait(proc_t *, sigtimedwait_args_t *, register_t *); struct sysent sysent[] = { [SYS_syscall] = { .nargs = 1, .call = (syscall_t *)sys_syscall }, @@ -179,5 +180,6 @@ struct sysent sysent[] = { [SYS_fsync] = { .nargs = 1, .call = (syscall_t *)sys_fsync }, [SYS_kqueue1] = { .nargs = 1, .call = (syscall_t *)sys_kqueue1 }, [SYS_kevent] = { .nargs = 6, .call = (syscall_t *)sys_kevent }, + [SYS_sigtimedwait] = { .nargs = 3, .call = (syscall_t *)sys_sigtimedwait }, }; From 7286e68b4dd76aef33d0de8a980b5e607f3d79f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Tue, 26 Jul 2022 13:47:47 +0200 Subject: [PATCH 02/35] First check tests to run then run init. --- sys/kern/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/kern/main.c b/sys/kern/main.c index 7bf642bf5b..7fe8455d4c 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -61,16 +61,16 @@ static __noreturn void start_init(__unused void *arg) { assert(_stdout == 1); assert(_stderr == 2); + char *test = kenv_get("test"); + if (test) + ktest_main(test); + char *init = kenv_get("init"); if (init == NULL) init = "/sbin/init"; kern_execve(init, kenv_get_init(), (char *[]){NULL}); - char *test = kenv_get("test"); - if (test) - ktest_main(test); - panic("Use init=PROGRAM to start a user-space program " "or test=TESTLIST to run tests."); } From 6f5ad93cbcf516830e41203037df3f6a57e7db1e Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Wed, 9 Nov 2022 18:24:00 +0100 Subject: [PATCH 03/35] wip --- build/tools.mk | 2 +- include/sys/sigtypes.h | 2 ++ launch | 4 +-- sys/kern/initrd.c | 4 +-- sys/kern/proc.c | 8 ++---- sys/kern/signal.c | 1 + sys/kern/syscalls.c | 57 ++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 64 insertions(+), 14 deletions(-) diff --git a/build/tools.mk b/build/tools.mk index d6fc2586ce..a6056e6fce 100644 --- a/build/tools.mk +++ b/build/tools.mk @@ -6,7 +6,7 @@ # The following make variables are set by the including makefile: # - TARGET, ABIFLAGS: Set by arch.*.mk files. -LLVM_VER := -14 +LLVM_VER := -13 ifeq ($(shell which ccache > /dev/null; echo $$?), 0) CCACHE := ccache diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index c130e4ccfc..1402669b3b 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -31,6 +31,8 @@ typedef struct { { (t)->__bits &= ~(s)->__bits; } #define __sigandset(s, t) \ { (t)->__bits &= (s)->__bits; } +#define __signandset(s, t) \ + { (t)->__bits &= ~((s)->__bits); } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) typedef struct sigaltstack { diff --git a/launch b/launch index 7a6d640a2b..87cec4e2ae 100755 --- a/launch +++ b/launch @@ -121,7 +121,7 @@ CONFIG = { 'drive': 'if=none,id=stick,file={path}', }, 'rpi3': { - 'binary': 'qemu-mimiker-aarch64', + 'binary': 'qemu-system-aarch64', 'options': [ '-machine', 'raspi3b', '-smp', '4', @@ -180,7 +180,7 @@ CONFIG = { 'binary': 'mipsel-mimiker-elf-gdb' }, 'rpi3': { - 'binary': 'aarch64-mimiker-elf-gdb' + 'binary': 'gdb-multiarch' }, 'litex-riscv': { 'binary': 'riscv32-mimiker-elf-gdb' diff --git a/sys/kern/initrd.c b/sys/kern/initrd.c index b2de15ef36..5148e4116f 100644 --- a/sys/kern/initrd.c +++ b/sys/kern/initrd.c @@ -367,9 +367,7 @@ size_t ramdisk_get_size(void) { void ramdisk_dump(void) { cpio_node_t *it; - TAILQ_FOREACH (it, &initrd_head, c_list) { - cpio_node_dump(it); - } + TAILQ_FOREACH (it, &initrd_head, c_list) { cpio_node_dump(it); } } static vfsops_t initrd_vfsops = { diff --git a/sys/kern/proc.c b/sys/kern/proc.c index e7d8f9da72..db45fb5a84 100644 --- a/sys/kern/proc.c +++ b/sys/kern/proc.c @@ -835,9 +835,7 @@ void proc_stop(signo_t sig) { proc_wakeup_parent(p->p_parent); sig_child(p, CLD_STOPPED); } - WITH_MTX_LOCK (td->td_lock) { - td->td_flags |= TDF_STOPPING; - } + WITH_MTX_LOCK (td->td_lock) { td->td_flags |= TDF_STOPPING; } proc_unlock(p); /* We're holding no locks here, so our process can be continued before we * actually stop the thread. This is why we need the TDF_STOPPING flag. */ @@ -866,7 +864,5 @@ void proc_continue(proc_t *p) { WITH_PROC_LOCK(p->p_parent) { proc_wakeup_parent(p->p_parent); } - WITH_MTX_LOCK (td->td_lock) { - thread_continue(td); - } + WITH_MTX_LOCK (td->td_lock) { thread_continue(td); } } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 3b883f0093..c802c688a6 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -543,6 +543,7 @@ int do_sigreturn(ucontext_t *ucp) { /* Restore user context. */ mcontext_copy(uctx, &uc.uc_mcontext); + // TODO sigsuspend tests (no "unmasking") WITH_MTX_LOCK (&td->td_proc->p_lock) error = do_sigprocmask(SIG_SETMASK, &uc.uc_sigmask, NULL); assert(error == 0); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 08e7b5b499..23738d567f 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1,4 +1,3 @@ -#define KL_LOG KL_SYSCALL #include #include #include @@ -26,6 +25,7 @@ #include #include +#include "sys/sigtypes.h" #include "sysent.h" /* Empty syscall handler, for unimplemented and deprecated syscall numbers. */ @@ -1312,7 +1312,60 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { return error; } +static int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + struct timespec *timeout) { + int timevalid = 0; + sigset_t saved_mask, new_block; + thread_t *td = p->p_thread; + + if (timeout != NULL) { + if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) { + timevalid = 1; + } + } + + bzero(kinfo, sizeof(*kinfo)); + + /* These signals cannot be waited for. */ + __sigdelset(&waitset, SIGKILL); + __sigdelset(&waitset, SIGSTOP); + + WITH_PROC_LOCK(p) { + saved_mask = td->td_sigmask; + __sigminusset(&td->td_sigmask, &waitset); + for (;;) { + + } + } +} + static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, register_t *res) { - return ENOTSUP; + const sigset_t *u_set = SCARG(args, set); + siginfo_t *u_info = SCARG(args, info); + const struct timespec *u_timeout = SCARG(args, timeout); + sigset_t set; + ksiginfo_t kinfo; + timespec_t timeout; + int error; + + if (u_timeout) { + error = copyin_s(u_timeout, timeout); + if (error) + return error; + } + + error = copyin_s(u_set, set); + if (error) + return error; + + error = do_sigtimedwait(p, set, &kinfo, &timeout); + if (error) + return error; + + if (u_info) { + error = copyout_s(kinfo.ksi_info, u_info); + } + + return error; } From 3d15ce3262fe8d4d6ee7f8f456df1c0f0cc83292 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 10 Nov 2022 13:11:56 +0100 Subject: [PATCH 04/35] [WIP] do_sigtimedwait --- include/sys/signal.h | 3 +++ include/sys/sigtypes.h | 2 -- include/sys/syscallargs.h | 1 - sys/kern/signal.c | 39 +++++++++++++++++++++++++++++++++++++++ sys/kern/syscalls.c | 27 --------------------------- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/include/sys/signal.h b/include/sys/signal.h index 2546c29dd3..9517b2d4d3 100644 --- a/include/sys/signal.h +++ b/include/sys/signal.h @@ -3,6 +3,7 @@ #include #include +#include #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ @@ -158,6 +159,8 @@ void sig_onexec(proc_t *p); int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset); int do_sigsuspend(proc_t *p, const sigset_t *mask); +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + struct timespec *timeout); int do_sigpending(proc_t *p, sigset_t *set); #endif /* !_KERNEL */ diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index 1402669b3b..c130e4ccfc 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -31,8 +31,6 @@ typedef struct { { (t)->__bits &= ~(s)->__bits; } #define __sigandset(s, t) \ { (t)->__bits &= (s)->__bits; } -#define __signandset(s, t) \ - { (t)->__bits &= ~((s)->__bits); } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) typedef struct sigaltstack { diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 89cd53a8af..58f7c9b5d1 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -9,7 +9,6 @@ #include #include #include - #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index c802c688a6..94a372c184 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -199,6 +199,45 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { return ERESTARTNOHAND; } +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + timespec_t *tsp) { + int timevalid = 0, sig, error, timeout; + sigset_t saved_mask, new_block; + thread_t *td = p->p_thread; + + if (tsp != NULL) { + if (tsp->tv_nsec >= 0 && tsp->tv_nsec < 1000000000) { + timevalid = 1; + timeout = ts2hz(tsp); + } + } + + bzero(kinfo, sizeof(*kinfo)); + + /* These signals cannot be waited for. */ + __sigdelset(&waitset, SIGKILL); + __sigdelset(&waitset, SIGSTOP); + + WITH_PROC_LOCK(p) { + saved_mask = td->td_sigmask; + __sigminusset(&td->td_sigmask, &waitset); + for (;;) { + /* if there's a pending non-blocked signal: return! */ + + /* FreeBSD says that POSIX says that this should be checked after + * checking if there's a pending signal */ + if (tsp != NULL && !timevalid) { + error = EINVAL; + break; + } + + error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + } + } + + return error; +} + int do_sigpending(proc_t *p, sigset_t *set) { SCOPED_MTX_LOCK(&p->p_lock); thread_t *td = p->p_thread; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 23738d567f..1bdaaae4ef 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1312,33 +1312,6 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { return error; } -static int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, - struct timespec *timeout) { - int timevalid = 0; - sigset_t saved_mask, new_block; - thread_t *td = p->p_thread; - - if (timeout != NULL) { - if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) { - timevalid = 1; - } - } - - bzero(kinfo, sizeof(*kinfo)); - - /* These signals cannot be waited for. */ - __sigdelset(&waitset, SIGKILL); - __sigdelset(&waitset, SIGSTOP); - - WITH_PROC_LOCK(p) { - saved_mask = td->td_sigmask; - __sigminusset(&td->td_sigmask, &waitset); - for (;;) { - - } - } -} - static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, register_t *res) { const sigset_t *u_set = SCARG(args, set); From 1ce829f841d96c425eebfcebad9e54e5142ffe56 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 18 Dec 2022 21:58:19 +0100 Subject: [PATCH 05/35] [WIP] Sigtimedwait finished, first test Finished sigtimedwait, but there's a bug, test crashes in some unexpected place. --- bin/utest/main.c | 1 + bin/utest/signal.c | 42 +++++++++++++++++++++++++++ bin/utest/utest.h | 1 + sys/kern/signal.c | 70 +++++++++++++++++++++++++++++++++------------ sys/kern/syscalls.c | 6 ++-- sys/tests/utest.c | 1 + 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/bin/utest/main.c b/bin/utest/main.c index 5edb229b6a..4f730f9b99 100644 --- a/bin/utest/main.c +++ b/bin/utest/main.c @@ -45,6 +45,7 @@ int main(int argc, char **argv) { CHECKRUN_TEST(signal_cont_masked); CHECKRUN_TEST(signal_mask); CHECKRUN_TEST(signal_mask_nonmaskable); + CHECKRUN_TEST(signal_sigtimedwait); CHECKRUN_TEST(signal_sigsuspend); CHECKRUN_TEST(signal_sigsuspend_stop); CHECKRUN_TEST(signal_handler_mask); diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 1608ac93c1..ba32f58782 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -282,6 +282,48 @@ int test_signal_sigsuspend(void) { return 0; } +/* ======= signal_sigtimedwait ======= */ +int test_signal_sigtimedwait(void) { + pid_t ppid = getpid(); + signal(SIGCONT, sigcont_handler); + signal(SIGUSR1, sigusr1_handler); + sigset_t set, current, waitset; + __sigfillset(&set); + __sigdelset(&set, SIGUSR1); + assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0); + pid_t cpid = fork(); + if (cpid == 0) { + for (int i = 0; i < 10; i++) { + kill(ppid, SIGCONT); + sched_yield(); + } + kill(ppid, SIGUSR1); + return 0; + } + /* Go to sleep with everything except SIGUSR1 blocked. */ + printf("Calling sigtimedwait()...\n"); + siginfo_t info; + __sigemptyset(&waitset); + __sigaddset(&waitset, SIGUSR1); + assert(sigtimedwait(&waitset, &info, NULL) == 0); + assert(info.si_signo == SIGUSR1); + sigprocmask(SIG_BLOCK, NULL, ¤t); + assert(__sigsetequal(&set, ¤t)); + assert(sigusr1_handled); + assert(!sigcont_handled); + __sigemptyset(&set); + __sigaddset(&set, SIGCONT); + assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0); + assert(sigcont_handled); + + printf("Waiting for child...\n"); + int status; + wait(&status); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 0); + return 0; +} + /* ======= signal_sigsuspend_stop ======= */ int test_signal_sigsuspend_stop(void) { pid_t ppid = getpid(); diff --git a/bin/utest/utest.h b/bin/utest/utest.h index 05afdd9b42..5b604b2d1a 100644 --- a/bin/utest/utest.h +++ b/bin/utest/utest.h @@ -37,6 +37,7 @@ int test_signal_stop(void); int test_signal_cont_masked(void); int test_signal_mask(void); int test_signal_mask_nonmaskable(void); +int test_signal_sigtimedwait(void); int test_signal_sigsuspend(void); int test_signal_sigsuspend_stop(void); int test_signal_handler_mask(void); diff --git a/sys/kern/signal.c b/sys/kern/signal.c index bb52476237..f563cb8b69 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -1,3 +1,4 @@ +#include "sys/sigtypes.h" #define KL_LOG KL_SIGNAL #include #include @@ -202,40 +203,74 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, timespec_t *tsp) { - int timevalid = 0, sig, error, timeout; - sigset_t saved_mask, new_block; + int timevalid = 0, error = 0, timeout = 0; + sigset_t saved_mask; + signo_t sig; thread_t *td = p->p_thread; if (tsp != NULL) { if (tsp->tv_nsec >= 0 && tsp->tv_nsec < 1000000000) { timevalid = 1; timeout = ts2hz(tsp); + /* Timeout set to 0 means to not block, but for sleepq it means to + * wait indefinitely */ + if (timeout == 0) { + if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { + timeout = -1; + } + else { + /* Shortest possible timeout */ + timeout = 1; + } + } } } bzero(kinfo, sizeof(*kinfo)); - /* These signals cannot be waited for. */ - __sigdelset(&waitset, SIGKILL); - __sigdelset(&waitset, SIGSTOP); + /* Silently ignore SIGKILL and SIGSTOP. */ + __sigminusset(&cantmask, &waitset); WITH_PROC_LOCK(p) { saved_mask = td->td_sigmask; - __sigminusset(&td->td_sigmask, &waitset); - for (;;) { - /* if there's a pending non-blocked signal: return! */ - - /* FreeBSD says that POSIX says that this should be checked after - * checking if there's a pending signal */ - if (tsp != NULL && !timevalid) { - error = EINVAL; - break; - } + __sigminusset(&waitset, &td->td_sigmask); - error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + /* Question: can I return in WITH_PROC_LOCK? */ + if ((sig = sig_pending(td))) { + error = 0; + goto out; } - } + if (timeout == -1) { + error = EAGAIN; + goto out; + } + + if (tsp != NULL && !timevalid) { + error = EINVAL; + goto out; + } + + error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + + if (error == ETIMEDOUT) { + error = EAGAIN; + goto out; + } + + sigset_t unblocked = td->td_sigpend.sp_set; + __sigandset(&waitset, &unblocked) + if (__sigfindset(&unblocked)) { + error = 0; + } + else { + error = EINTR; + } + +out: + td->td_sigmask = saved_mask; + } + return error; } @@ -583,7 +618,6 @@ int do_sigreturn(ucontext_t *ucp) { /* Restore user context. */ mcontext_copy(uctx, &uc.uc_mcontext); - // TODO sigsuspend tests (no "unmasking") WITH_MTX_LOCK (&td->td_proc->p_lock) error = do_sigprocmask(SIG_SETMASK, &uc.uc_sigmask, NULL); assert(error == 0); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 1bdaaae4ef..46ca77e34f 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1319,11 +1319,13 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, const struct timespec *u_timeout = SCARG(args, timeout); sigset_t set; ksiginfo_t kinfo; - timespec_t timeout; + timespec_t timeout = {}; + timespec_t *tsp = NULL; int error; if (u_timeout) { error = copyin_s(u_timeout, timeout); + tsp = &timeout; if (error) return error; } @@ -1332,7 +1334,7 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, if (error) return error; - error = do_sigtimedwait(p, set, &kinfo, &timeout); + error = do_sigtimedwait(p, set, &kinfo, tsp); if (error) return error; diff --git a/sys/tests/utest.c b/sys/tests/utest.c index 4629018568..50878aec7f 100644 --- a/sys/tests/utest.c +++ b/sys/tests/utest.c @@ -90,6 +90,7 @@ UTEST_ADD_SIMPLE(signal_stop); UTEST_ADD_SIMPLE(signal_cont_masked); UTEST_ADD_SIMPLE(signal_mask); UTEST_ADD_SIMPLE(signal_mask_nonmaskable); +UTEST_ADD_SIMPLE(signal_sigtimedwait); UTEST_ADD_SIMPLE(signal_sigsuspend); UTEST_ADD_SIMPLE(signal_sigsuspend_stop); UTEST_ADD_SIMPLE(signal_handler_mask); From 000d730b7ed7b8d3a234bb609d50ed08339282bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Tue, 26 Jul 2022 13:22:24 +0200 Subject: [PATCH 06/35] Add /sbin/init based on suckless sinit. --- Makefile | 2 +- etc/Makefile | 5 ++- etc/rc.init | 13 ++++++ etc/rc.shutdown | 3 ++ include/signal.h | 8 ++++ include/sys/syscall.h | 3 +- include/sys/syscallargs.h | 8 ++++ lib/libc/sys/sigwait.c | 56 ++++++++++++++++++++++++ lib/libc/sys/syscalls.S | 1 + sbin/Makefile | 9 ++++ sbin/init/LICENSE | 21 +++++++++ sbin/init/Makefile | 6 +++ sbin/init/README | 26 +++++++++++ sbin/init/config.h | 5 +++ sbin/init/init.8 | 60 ++++++++++++++++++++++++++ sbin/init/init.c | 91 +++++++++++++++++++++++++++++++++++++++ sys/kern/main.c | 6 ++- sys/kern/syscalls.c | 5 +++ sys/kern/syscalls.master | 2 + sys/kern/sysent.h | 1 + 20 files changed, 326 insertions(+), 5 deletions(-) create mode 100755 etc/rc.init create mode 100755 etc/rc.shutdown create mode 100644 lib/libc/sys/sigwait.c create mode 100644 sbin/Makefile create mode 100644 sbin/init/LICENSE create mode 100644 sbin/init/Makefile create mode 100644 sbin/init/README create mode 100644 sbin/init/config.h create mode 100644 sbin/init/init.8 create mode 100644 sbin/init/init.c diff --git a/Makefile b/Makefile index 503945af9d..ff65e04551 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ TOPDIR = $(CURDIR) # Directories which require calling make recursively -SUBDIR = sys lib bin usr.bin etc include contrib +SUBDIR = sys lib bin usr.bin sbin etc include contrib all: install diff --git a/etc/Makefile b/etc/Makefile index 7e1a7c7681..f5c24a2687 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -2,7 +2,7 @@ TOPDIR = $(realpath ..) -FILES = group master.passwd .kshrc shells +FILES = group master.passwd rc.init rc.shutdown .kshrc shells INSTALL-FILES = $(addprefix $(SYSROOT)/etc/, $(FILES)) all: build @@ -12,3 +12,6 @@ include $(TOPDIR)/build/common.mk $(SYSROOT)/etc/%: % echo "[INSTALL] $(DIR)$* -> /etc/$*" $(INSTALL) -m 644 -D $< $@ + +install-here: + chmod 755 $(SYSROOT)/etc/rc.* diff --git a/etc/rc.init b/etc/rc.init new file mode 100755 index 0000000000..5ef891b160 --- /dev/null +++ b/etc/rc.init @@ -0,0 +1,13 @@ +#!/bin/ksh + +umask 022 + +echo " __ __ _ _ _ ____ _____ " +echo " | \/ (_) (_) | / __ \ / ____| " +echo " | \ / |_ _ __ ___ _| | _____ _ __| | | | (___ " +echo " | |\/| | | '_ \` _ \| | |/ / _ \ '__| | | |\___ \ " +echo " | | | | | | | | | | | < __/ | | |__| |____) | " +echo " |_| |_|_|_| |_| |_|_|_|\_\___|_| \____/|_____/ " +echo + +exec /bin/ksh diff --git a/etc/rc.shutdown b/etc/rc.shutdown new file mode 100755 index 0000000000..2652955025 --- /dev/null +++ b/etc/rc.shutdown @@ -0,0 +1,3 @@ +#!/bin/ksh + +echo "Shutdown not supported yet!" diff --git a/include/signal.h b/include/signal.h index fa5d84fcae..907dad28bb 100644 --- a/include/signal.h +++ b/include/signal.h @@ -35,6 +35,7 @@ #define _SIGNAL_H_ #include +#include #include __BEGIN_DECLS @@ -68,6 +69,13 @@ int sigsuspend(const sigset_t *); int killpg(int pgrp, int sig); int siginterrupt(int sig, int flag); +/* + * X/Open CAE Specification Issue 5; IEEE Std 1003.1b-1993 (POSIX) + */ +int sigwait(const sigset_t *__restrict, int *__restrict); +int sigtimedwait(const sigset_t *__restrict set, siginfo_t *__restrict info, + const struct timespec *__restrict timeout); + /* * Mimiker specific stuff. */ diff --git a/include/sys/syscall.h b/include/sys/syscall.h index 70af2a5d63..94e3e21b18 100644 --- a/include/sys/syscall.h +++ b/include/sys/syscall.h @@ -91,6 +91,7 @@ #define SYS_fsync 83 #define SYS_kqueue1 84 #define SYS_kevent 85 -#define SYS_MAXSYSCALL 86 +#define SYS_sigtimedwait 86 +#define SYS_MAXSYSCALL 87 #define SYS_MAXSYSARGS 6 diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 28ad24bd10..89cd53a8af 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -8,6 +8,8 @@ #include #include #include +#include + #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } @@ -435,3 +437,9 @@ typedef struct { SYSCALLARG(size_t) nevents; SYSCALLARG(const struct timespec *) timeout; } kevent_args_t; + +typedef struct { + SYSCALLARG(const sigset_t *) set; + SYSCALLARG(siginfo_t *) info; + SYSCALLARG(struct timespec *) timeout; +} sigtimedwait_args_t; diff --git a/lib/libc/sys/sigwait.c b/lib/libc/sys/sigwait.c new file mode 100644 index 0000000000..408ba03767 --- /dev/null +++ b/lib/libc/sys/sigwait.c @@ -0,0 +1,56 @@ +/* $NetBSD: sigwait.c,v 1.5 2012/03/20 16:26:12 matt Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * This is wrapper around sigtimedwait(2), providing sigwait() + * implementation for userland. + */ +int +sigwait(const sigset_t * __restrict set, int * __restrict signum) +{ + int saved_errno, new_errno, sig; + + saved_errno = errno; + sig = sigtimedwait(set, NULL, NULL); + new_errno = errno; + errno = saved_errno; + if (sig < 0) + return (new_errno); + *signum = sig; + return (0); +} diff --git a/lib/libc/sys/syscalls.S b/lib/libc/sys/syscalls.S index d95634e12b..8dd567cc04 100644 --- a/lib/libc/sys/syscalls.S +++ b/lib/libc/sys/syscalls.S @@ -84,3 +84,4 @@ SYSCALL(sync, SYS_sync) SYSCALL(fsync, SYS_fsync) SYSCALL(kqueue1, SYS_kqueue1) SYSCALL(kevent, SYS_kevent) +SYSCALL(sigtimedwait, SYS_sigtimedwait) diff --git a/sbin/Makefile b/sbin/Makefile new file mode 100644 index 0000000000..499be24f06 --- /dev/null +++ b/sbin/Makefile @@ -0,0 +1,9 @@ +# vim: tabstop=8 shiftwidth=8 noexpandtab: + +TOPDIR = $(realpath ..) + +SUBDIR = init + +all: build + +include $(TOPDIR)/build/common.mk diff --git a/sbin/init/LICENSE b/sbin/init/LICENSE new file mode 100644 index 0000000000..91b577935b --- /dev/null +++ b/sbin/init/LICENSE @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2014-2015 Dimitris Papastamos + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/sbin/init/Makefile b/sbin/init/Makefile new file mode 100644 index 0000000000..aaf2853bcc --- /dev/null +++ b/sbin/init/Makefile @@ -0,0 +1,6 @@ +TOPDIR = $(realpath ../..) + +PROGRAM = init +FORMAT-EXCLUDE = $(SOURCES) + +include $(TOPDIR)/build/build.prog.mk diff --git a/sbin/init/README b/sbin/init/README new file mode 100644 index 0000000000..13642b83a1 --- /dev/null +++ b/sbin/init/README @@ -0,0 +1,26 @@ +sinit - suckless init +===================== + +sinit is a simple init. It was initially based on +Rich Felker's minimal init[1]. + +Why? +---- + +I wanted to get rid of Busybox init on my toy distro[2]. + +How? +---- + +There are 3 signals that sinit will act on. + + SIGUSR1: powers off the machine. + SIGINT: reboots the machine (or alternatively via ctrl-alt-del). + SIGCHLD: reap children + +To see how sinit integrates with the init scripts, then have +a look at [3]. + +[1] https://gist.github.com/rofl0r/6168719 +[2] http://git.2f30.org/morpheus/ +[3] http://git.2f30.org/ports/tree/fs/ diff --git a/sbin/init/config.h b/sbin/init/config.h new file mode 100644 index 0000000000..3d2da6fcb6 --- /dev/null +++ b/sbin/init/config.h @@ -0,0 +1,5 @@ +/* See LICENSE file for copyright and license details. */ + +static char *const rcinitcmd[] = { "/etc/rc.init", NULL }; +static char *const rcrebootcmd[] = { "/etc/rc.shutdown", "reboot", NULL }; +static char *const rcpoweroffcmd[] = { "/etc/rc.shutdown", "poweroff", NULL }; diff --git a/sbin/init/init.8 b/sbin/init/init.8 new file mode 100644 index 0000000000..605b457bd2 --- /dev/null +++ b/sbin/init/init.8 @@ -0,0 +1,60 @@ +.Dd December 4, 2014 +.Dt SINIT 8 sinit\-1.1 +.Os +.Sh NAME +.Nm sinit +.Nd simple init +.Sh DESCRIPTION +.Nm +is a simple init. It is configured by modifying +.Dq config.h +and recompiling the code. +.Ss Init sequence +By default +.Nm +will execute +.Dq /bin/rc.init . +You can chain your init scripts together at that point to allow for +single-user and multi-user operation. +.Ss Signal handling +.Nm +will respond to the following signals: +.Bl -tag -width xxxxxxxx +.It USR1 +Default action is to initiate the shutdown sequence by +executing +.Dq /bin/rc.shutdown poweroff . +.It INT +Default action is to initiate the reboot sequence by +executing +.Dq /bin/rc.shutdown reboot . +.It CHLD +Reap children. +.El +.Ss General considerations +Running the +.Dq rc.shutdown +script directly is not recommended. If any +process in your session has stale filesystem references then it is +likely your init scripts will fail to unmount the filesystem cleanly. +It is recommended to signal +.Nm +via a wrapper script. +.Pp +.Nm +does not clear utmp records. The version of +.Xr getty 8 +in ubase clears the utmp entries on the specified tty before it +spawns the given program, usually +.Xr login 1 . +.Pp +.Nm +does not restart +.Xr getty 8 +or interact with it in any way. You will need an external +respawning mechanism to restart it. +.Sh SEE ALSO +.Xr getty 8 , +.Xr killall5 8 +.Sh AUTHORS +.An Dimitris Papastamos Aq Mt sin@2f30.org . diff --git a/sbin/init/init.c b/sbin/init/init.c new file mode 100644 index 0000000000..716671087f --- /dev/null +++ b/sbin/init/init.c @@ -0,0 +1,91 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include + +#include +#include +#include +#include + +#define LEN(x) (sizeof (x) / sizeof *(x)) +#define TIMEO 30 + +static void sigpoweroff(void); +static void sigreap(void); +static void sigreboot(void); +static void spawn(char *const []); + +static struct { + int sig; + void (*handler)(void); +} sigmap[] = { + { SIGUSR1, sigpoweroff }, + { SIGCHLD, sigreap }, + { SIGALRM, sigreap }, + { SIGINT, sigreboot }, +}; + +#include "config.h" + +static sigset_t set; + +int +main(void) +{ + int sig; + size_t i; + + if (getpid() != 1) + return 1; + chdir("/"); + sigfillset(&set); + sigprocmask(SIG_BLOCK, &set, NULL); + spawn(rcinitcmd); + while (1) { + alarm(TIMEO); + sigwait(&set, &sig); + for (i = 0; i < LEN(sigmap); i++) { + if (sigmap[i].sig == sig) { + sigmap[i].handler(); + break; + } + } + } + /* not reachable */ + return 0; +} + +static void +sigpoweroff(void) +{ + spawn(rcpoweroffcmd); +} + +static void +sigreap(void) +{ + while (waitpid(-1, NULL, WNOHANG) > 0) + ; + alarm(TIMEO); +} + +static void +sigreboot(void) +{ + spawn(rcrebootcmd); +} + +static void +spawn(char *const argv[]) +{ + switch (fork()) { + case 0: + sigprocmask(SIG_UNBLOCK, &set, NULL); + setsid(); + execvp(argv[0], argv); + perror("execvp"); + _exit(1); + case -1: + perror("fork"); + } +} diff --git a/sys/kern/main.c b/sys/kern/main.c index 4fd54ed375..90d8ed2e90 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -68,8 +68,10 @@ static __noreturn void start_init(__unused void *arg) { assert(_stderr == 2); char *init = kenv_get("init"); - if (init) - kern_execve(init, kenv_get_init(), (char *[]){NULL}); + if (init == NULL) + init = "/sbin/init"; + + kern_execve(init, kenv_get_init(), (char *[]){NULL}); char *test = kenv_get("test"); if (test) diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 0a4c58506a..08e7b5b499 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1311,3 +1311,8 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { kfree(M_TEMP, eventlist); return error; } + +static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, + register_t *res) { + return ENOTSUP; +} diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 6eaa152e38..7798c808f1 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -4,6 +4,7 @@ #include #include #include +#include #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } @@ -99,5 +100,6 @@ 83 { int sys_fsync(int fd); } 84 { int sys_kqueue1(int flags); } 85 { int sys_kevent(int kq, const struct kevent *changelist, size_t nchanges, struct kevent *eventlist, size_t nevents, const struct timespec *timeout); } +86 { int sys_sigtimedwait(const sigset_t *set, siginfo_t *info, struct timespec *timeout); } ; vim: ts=4 sw=4 sts=4 et diff --git a/sys/kern/sysent.h b/sys/kern/sysent.h index e295672f1b..5014844b50 100644 --- a/sys/kern/sysent.h +++ b/sys/kern/sysent.h @@ -91,6 +91,7 @@ static int sys_sync(proc_t *, void *, register_t *); static int sys_fsync(proc_t *, fsync_args_t *, register_t *); static int sys_kqueue1(proc_t *, kqueue1_args_t *, register_t *); static int sys_kevent(proc_t *, kevent_args_t *, register_t *); +static int sys_sigtimedwait(proc_t *, sigtimedwait_args_t *, register_t *); struct sysent sysent[] = { [SYS_syscall] = { .name = "syscall", .nargs = 1, .call = (syscall_t *)sys_syscall }, From 2d7ca280e42f85e06867e6f5e2b8160471a0f637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Tue, 26 Jul 2022 13:47:47 +0200 Subject: [PATCH 07/35] First check tests to run then run init. --- sys/kern/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/kern/main.c b/sys/kern/main.c index 90d8ed2e90..1cd9de8d06 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -67,16 +67,16 @@ static __noreturn void start_init(__unused void *arg) { assert(_stdout == 1); assert(_stderr == 2); + char *test = kenv_get("test"); + if (test) + ktest_main(test); + char *init = kenv_get("init"); if (init == NULL) init = "/sbin/init"; kern_execve(init, kenv_get_init(), (char *[]){NULL}); - char *test = kenv_get("test"); - if (test) - ktest_main(test); - panic("Use init=PROGRAM to start a user-space program " "or test=TESTLIST to run tests."); } From b38690932692c9ffe26089b6c7fb886bf283505f Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Wed, 9 Nov 2022 18:24:00 +0100 Subject: [PATCH 08/35] wip --- build/tools.mk | 2 +- include/sys/sigtypes.h | 2 ++ launch | 4 +-- sys/kern/initrd.c | 4 +-- sys/kern/proc.c | 8 ++---- sys/kern/signal.c | 1 + sys/kern/syscalls.c | 57 ++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 64 insertions(+), 14 deletions(-) diff --git a/build/tools.mk b/build/tools.mk index d6fc2586ce..a6056e6fce 100644 --- a/build/tools.mk +++ b/build/tools.mk @@ -6,7 +6,7 @@ # The following make variables are set by the including makefile: # - TARGET, ABIFLAGS: Set by arch.*.mk files. -LLVM_VER := -14 +LLVM_VER := -13 ifeq ($(shell which ccache > /dev/null; echo $$?), 0) CCACHE := ccache diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index 36c04d467c..717b0a6313 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -31,6 +31,8 @@ typedef struct { { (t)->__bits &= ~(s)->__bits; } #define __sigandset(s, t) \ { (t)->__bits &= (s)->__bits; } +#define __signandset(s, t) \ + { (t)->__bits &= ~((s)->__bits); } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) typedef struct sigaltstack { diff --git a/launch b/launch index bb6c792865..92c68c35ae 100755 --- a/launch +++ b/launch @@ -121,7 +121,7 @@ CONFIG = { 'drive': 'if=none,id=stick,file={path}', }, 'rpi3': { - 'binary': 'qemu-mimiker-aarch64', + 'binary': 'qemu-system-aarch64', 'options': [ '-machine', 'raspi3b', '-smp', '4', @@ -180,7 +180,7 @@ CONFIG = { 'binary': 'mipsel-mimiker-elf-gdb' }, 'rpi3': { - 'binary': 'aarch64-mimiker-elf-gdb' + 'binary': 'gdb-multiarch' }, 'litex-riscv': { 'binary': 'riscv32-mimiker-elf-gdb' diff --git a/sys/kern/initrd.c b/sys/kern/initrd.c index b2de15ef36..5148e4116f 100644 --- a/sys/kern/initrd.c +++ b/sys/kern/initrd.c @@ -367,9 +367,7 @@ size_t ramdisk_get_size(void) { void ramdisk_dump(void) { cpio_node_t *it; - TAILQ_FOREACH (it, &initrd_head, c_list) { - cpio_node_dump(it); - } + TAILQ_FOREACH (it, &initrd_head, c_list) { cpio_node_dump(it); } } static vfsops_t initrd_vfsops = { diff --git a/sys/kern/proc.c b/sys/kern/proc.c index e7d8f9da72..db45fb5a84 100644 --- a/sys/kern/proc.c +++ b/sys/kern/proc.c @@ -835,9 +835,7 @@ void proc_stop(signo_t sig) { proc_wakeup_parent(p->p_parent); sig_child(p, CLD_STOPPED); } - WITH_MTX_LOCK (td->td_lock) { - td->td_flags |= TDF_STOPPING; - } + WITH_MTX_LOCK (td->td_lock) { td->td_flags |= TDF_STOPPING; } proc_unlock(p); /* We're holding no locks here, so our process can be continued before we * actually stop the thread. This is why we need the TDF_STOPPING flag. */ @@ -866,7 +864,5 @@ void proc_continue(proc_t *p) { WITH_PROC_LOCK(p->p_parent) { proc_wakeup_parent(p->p_parent); } - WITH_MTX_LOCK (td->td_lock) { - thread_continue(td); - } + WITH_MTX_LOCK (td->td_lock) { thread_continue(td); } } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 00b2c0aed5..b895774d56 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -576,6 +576,7 @@ int do_sigreturn(ucontext_t *ucp) { /* Restore user context. */ mcontext_copy(uctx, &uc.uc_mcontext); + // TODO sigsuspend tests (no "unmasking") WITH_MTX_LOCK (&td->td_proc->p_lock) error = do_sigprocmask(SIG_SETMASK, &uc.uc_sigmask, NULL); assert(error == 0); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 08e7b5b499..23738d567f 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1,4 +1,3 @@ -#define KL_LOG KL_SYSCALL #include #include #include @@ -26,6 +25,7 @@ #include #include +#include "sys/sigtypes.h" #include "sysent.h" /* Empty syscall handler, for unimplemented and deprecated syscall numbers. */ @@ -1312,7 +1312,60 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { return error; } +static int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + struct timespec *timeout) { + int timevalid = 0; + sigset_t saved_mask, new_block; + thread_t *td = p->p_thread; + + if (timeout != NULL) { + if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) { + timevalid = 1; + } + } + + bzero(kinfo, sizeof(*kinfo)); + + /* These signals cannot be waited for. */ + __sigdelset(&waitset, SIGKILL); + __sigdelset(&waitset, SIGSTOP); + + WITH_PROC_LOCK(p) { + saved_mask = td->td_sigmask; + __sigminusset(&td->td_sigmask, &waitset); + for (;;) { + + } + } +} + static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, register_t *res) { - return ENOTSUP; + const sigset_t *u_set = SCARG(args, set); + siginfo_t *u_info = SCARG(args, info); + const struct timespec *u_timeout = SCARG(args, timeout); + sigset_t set; + ksiginfo_t kinfo; + timespec_t timeout; + int error; + + if (u_timeout) { + error = copyin_s(u_timeout, timeout); + if (error) + return error; + } + + error = copyin_s(u_set, set); + if (error) + return error; + + error = do_sigtimedwait(p, set, &kinfo, &timeout); + if (error) + return error; + + if (u_info) { + error = copyout_s(kinfo.ksi_info, u_info); + } + + return error; } From fb3eaa3df20a0e577a32c6da728a22a74e6723bf Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 10 Nov 2022 13:11:56 +0100 Subject: [PATCH 09/35] [WIP] do_sigtimedwait --- include/sys/signal.h | 3 +++ include/sys/sigtypes.h | 2 -- include/sys/syscallargs.h | 1 - sys/kern/signal.c | 39 +++++++++++++++++++++++++++++++++++++++ sys/kern/syscalls.c | 27 --------------------------- 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/include/sys/signal.h b/include/sys/signal.h index ba2da4d745..4cf6d07888 100644 --- a/include/sys/signal.h +++ b/include/sys/signal.h @@ -3,6 +3,7 @@ #include #include +#include #define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ @@ -201,6 +202,8 @@ void sig_onexec(proc_t *p); int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset); int do_sigsuspend(proc_t *p, const sigset_t *mask); +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + struct timespec *timeout); int do_sigpending(proc_t *p, sigset_t *set); #endif /* !_KERNEL */ diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index 717b0a6313..36c04d467c 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -31,8 +31,6 @@ typedef struct { { (t)->__bits &= ~(s)->__bits; } #define __sigandset(s, t) \ { (t)->__bits &= (s)->__bits; } -#define __signandset(s, t) \ - { (t)->__bits &= ~((s)->__bits); } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) typedef struct sigaltstack { diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 89cd53a8af..58f7c9b5d1 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -9,7 +9,6 @@ #include #include #include - #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index b895774d56..8f44035587 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -201,6 +201,45 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { return ERESTARTNOHAND; } +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, + timespec_t *tsp) { + int timevalid = 0, sig, error, timeout; + sigset_t saved_mask, new_block; + thread_t *td = p->p_thread; + + if (tsp != NULL) { + if (tsp->tv_nsec >= 0 && tsp->tv_nsec < 1000000000) { + timevalid = 1; + timeout = ts2hz(tsp); + } + } + + bzero(kinfo, sizeof(*kinfo)); + + /* These signals cannot be waited for. */ + __sigdelset(&waitset, SIGKILL); + __sigdelset(&waitset, SIGSTOP); + + WITH_PROC_LOCK(p) { + saved_mask = td->td_sigmask; + __sigminusset(&td->td_sigmask, &waitset); + for (;;) { + /* if there's a pending non-blocked signal: return! */ + + /* FreeBSD says that POSIX says that this should be checked after + * checking if there's a pending signal */ + if (tsp != NULL && !timevalid) { + error = EINVAL; + break; + } + + error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + } + } + + return error; +} + int do_sigpending(proc_t *p, sigset_t *set) { SCOPED_MTX_LOCK(&p->p_lock); thread_t *td = p->p_thread; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 23738d567f..1bdaaae4ef 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1312,33 +1312,6 @@ static int sys_kevent(proc_t *p, kevent_args_t *args, register_t *res) { return error; } -static int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, - struct timespec *timeout) { - int timevalid = 0; - sigset_t saved_mask, new_block; - thread_t *td = p->p_thread; - - if (timeout != NULL) { - if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) { - timevalid = 1; - } - } - - bzero(kinfo, sizeof(*kinfo)); - - /* These signals cannot be waited for. */ - __sigdelset(&waitset, SIGKILL); - __sigdelset(&waitset, SIGSTOP); - - WITH_PROC_LOCK(p) { - saved_mask = td->td_sigmask; - __sigminusset(&td->td_sigmask, &waitset); - for (;;) { - - } - } -} - static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, register_t *res) { const sigset_t *u_set = SCARG(args, set); From e41929e6d4c6628ae38df5785eb6ccd892127023 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 18 Dec 2022 21:58:19 +0100 Subject: [PATCH 10/35] [WIP] Sigtimedwait finished, first test Finished sigtimedwait, but there's a bug, test crashes in some unexpected place. --- bin/utest/main.c | 1 + bin/utest/signal.c | 42 +++++++++++++++++++++++++++ bin/utest/utest.h | 1 + sys/kern/signal.c | 70 +++++++++++++++++++++++++++++++++------------ sys/kern/syscalls.c | 6 ++-- sys/tests/utest.c | 1 + 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/bin/utest/main.c b/bin/utest/main.c index fea5f16f95..70b98d83bd 100644 --- a/bin/utest/main.c +++ b/bin/utest/main.c @@ -48,6 +48,7 @@ int main(int argc, char **argv) { CHECKRUN_TEST(signal_cont_masked); CHECKRUN_TEST(signal_mask); CHECKRUN_TEST(signal_mask_nonmaskable); + CHECKRUN_TEST(signal_sigtimedwait); CHECKRUN_TEST(signal_sigsuspend); CHECKRUN_TEST(signal_sigsuspend_stop); CHECKRUN_TEST(signal_handler_mask); diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 06938d586a..e9c69eef2d 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -287,6 +287,48 @@ int test_signal_sigsuspend(void) { return 0; } +/* ======= signal_sigtimedwait ======= */ +int test_signal_sigtimedwait(void) { + pid_t ppid = getpid(); + signal(SIGCONT, sigcont_handler); + signal(SIGUSR1, sigusr1_handler); + sigset_t set, current, waitset; + __sigfillset(&set); + __sigdelset(&set, SIGUSR1); + assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0); + pid_t cpid = fork(); + if (cpid == 0) { + for (int i = 0; i < 10; i++) { + kill(ppid, SIGCONT); + sched_yield(); + } + kill(ppid, SIGUSR1); + return 0; + } + /* Go to sleep with everything except SIGUSR1 blocked. */ + printf("Calling sigtimedwait()...\n"); + siginfo_t info; + __sigemptyset(&waitset); + __sigaddset(&waitset, SIGUSR1); + assert(sigtimedwait(&waitset, &info, NULL) == 0); + assert(info.si_signo == SIGUSR1); + sigprocmask(SIG_BLOCK, NULL, ¤t); + assert(__sigsetequal(&set, ¤t)); + assert(sigusr1_handled); + assert(!sigcont_handled); + __sigemptyset(&set); + __sigaddset(&set, SIGCONT); + assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0); + assert(sigcont_handled); + + printf("Waiting for child...\n"); + int status; + wait(&status); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 0); + return 0; +} + /* ======= signal_sigsuspend_stop ======= */ int test_signal_sigsuspend_stop(void) { pid_t ppid = getpid(); diff --git a/bin/utest/utest.h b/bin/utest/utest.h index 96b2b6791b..62f31d3565 100644 --- a/bin/utest/utest.h +++ b/bin/utest/utest.h @@ -41,6 +41,7 @@ int test_signal_stop(void); int test_signal_cont_masked(void); int test_signal_mask(void); int test_signal_mask_nonmaskable(void); +int test_signal_sigtimedwait(void); int test_signal_sigsuspend(void); int test_signal_sigsuspend_stop(void); int test_signal_handler_mask(void); diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 8f44035587..34908768b8 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -1,3 +1,4 @@ +#include "sys/sigtypes.h" #define KL_LOG KL_SIGNAL #include #include @@ -203,40 +204,74 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, timespec_t *tsp) { - int timevalid = 0, sig, error, timeout; - sigset_t saved_mask, new_block; + int timevalid = 0, error = 0, timeout = 0; + sigset_t saved_mask; + signo_t sig; thread_t *td = p->p_thread; if (tsp != NULL) { if (tsp->tv_nsec >= 0 && tsp->tv_nsec < 1000000000) { timevalid = 1; timeout = ts2hz(tsp); + /* Timeout set to 0 means to not block, but for sleepq it means to + * wait indefinitely */ + if (timeout == 0) { + if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { + timeout = -1; + } + else { + /* Shortest possible timeout */ + timeout = 1; + } + } } } bzero(kinfo, sizeof(*kinfo)); - /* These signals cannot be waited for. */ - __sigdelset(&waitset, SIGKILL); - __sigdelset(&waitset, SIGSTOP); + /* Silently ignore SIGKILL and SIGSTOP. */ + __sigminusset(&cantmask, &waitset); WITH_PROC_LOCK(p) { saved_mask = td->td_sigmask; - __sigminusset(&td->td_sigmask, &waitset); - for (;;) { - /* if there's a pending non-blocked signal: return! */ - - /* FreeBSD says that POSIX says that this should be checked after - * checking if there's a pending signal */ - if (tsp != NULL && !timevalid) { - error = EINVAL; - break; - } + __sigminusset(&waitset, &td->td_sigmask); - error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + /* Question: can I return in WITH_PROC_LOCK? */ + if ((sig = sig_pending(td))) { + error = 0; + goto out; } - } + if (timeout == -1) { + error = EAGAIN; + goto out; + } + + if (tsp != NULL && !timevalid) { + error = EINVAL; + goto out; + } + + error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); + + if (error == ETIMEDOUT) { + error = EAGAIN; + goto out; + } + + sigset_t unblocked = td->td_sigpend.sp_set; + __sigandset(&waitset, &unblocked) + if (__sigfindset(&unblocked)) { + error = 0; + } + else { + error = EINTR; + } + +out: + td->td_sigmask = saved_mask; + } + return error; } @@ -615,7 +650,6 @@ int do_sigreturn(ucontext_t *ucp) { /* Restore user context. */ mcontext_copy(uctx, &uc.uc_mcontext); - // TODO sigsuspend tests (no "unmasking") WITH_MTX_LOCK (&td->td_proc->p_lock) error = do_sigprocmask(SIG_SETMASK, &uc.uc_sigmask, NULL); assert(error == 0); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 1bdaaae4ef..46ca77e34f 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1319,11 +1319,13 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, const struct timespec *u_timeout = SCARG(args, timeout); sigset_t set; ksiginfo_t kinfo; - timespec_t timeout; + timespec_t timeout = {}; + timespec_t *tsp = NULL; int error; if (u_timeout) { error = copyin_s(u_timeout, timeout); + tsp = &timeout; if (error) return error; } @@ -1332,7 +1334,7 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, if (error) return error; - error = do_sigtimedwait(p, set, &kinfo, &timeout); + error = do_sigtimedwait(p, set, &kinfo, tsp); if (error) return error; diff --git a/sys/tests/utest.c b/sys/tests/utest.c index 06201b8a4c..9bd573cce1 100644 --- a/sys/tests/utest.c +++ b/sys/tests/utest.c @@ -98,6 +98,7 @@ UTEST_ADD_SIMPLE(signal_stop); UTEST_ADD_SIMPLE(signal_cont_masked); UTEST_ADD_SIMPLE(signal_mask); UTEST_ADD_SIMPLE(signal_mask_nonmaskable); +UTEST_ADD_SIMPLE(signal_sigtimedwait); UTEST_ADD_SIMPLE(signal_sigsuspend); UTEST_ADD_SIMPLE(signal_sigsuspend_stop); UTEST_ADD_SIMPLE(signal_handler_mask); From 35a1ecc061a5d8038527f3b8b92ebbdc11e592e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Sun, 18 Dec 2022 22:36:10 +0100 Subject: [PATCH 11/35] Fixes after merge. --- bin/utest/signal.c | 2 +- build/tools.mk | 2 +- sys/kern/initrd.c | 4 +++- sys/kern/proc.c | 8 ++++++-- sys/kern/signal.c | 16 +++++++--------- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index e9c69eef2d..ac6a3915c5 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -305,7 +305,7 @@ int test_signal_sigtimedwait(void) { kill(ppid, SIGUSR1); return 0; } - /* Go to sleep with everything except SIGUSR1 blocked. */ + /* Go to sleep with everything except SIGUSR1 blocked. */ printf("Calling sigtimedwait()...\n"); siginfo_t info; __sigemptyset(&waitset); diff --git a/build/tools.mk b/build/tools.mk index a6056e6fce..d6fc2586ce 100644 --- a/build/tools.mk +++ b/build/tools.mk @@ -6,7 +6,7 @@ # The following make variables are set by the including makefile: # - TARGET, ABIFLAGS: Set by arch.*.mk files. -LLVM_VER := -13 +LLVM_VER := -14 ifeq ($(shell which ccache > /dev/null; echo $$?), 0) CCACHE := ccache diff --git a/sys/kern/initrd.c b/sys/kern/initrd.c index 5148e4116f..b2de15ef36 100644 --- a/sys/kern/initrd.c +++ b/sys/kern/initrd.c @@ -367,7 +367,9 @@ size_t ramdisk_get_size(void) { void ramdisk_dump(void) { cpio_node_t *it; - TAILQ_FOREACH (it, &initrd_head, c_list) { cpio_node_dump(it); } + TAILQ_FOREACH (it, &initrd_head, c_list) { + cpio_node_dump(it); + } } static vfsops_t initrd_vfsops = { diff --git a/sys/kern/proc.c b/sys/kern/proc.c index db45fb5a84..e7d8f9da72 100644 --- a/sys/kern/proc.c +++ b/sys/kern/proc.c @@ -835,7 +835,9 @@ void proc_stop(signo_t sig) { proc_wakeup_parent(p->p_parent); sig_child(p, CLD_STOPPED); } - WITH_MTX_LOCK (td->td_lock) { td->td_flags |= TDF_STOPPING; } + WITH_MTX_LOCK (td->td_lock) { + td->td_flags |= TDF_STOPPING; + } proc_unlock(p); /* We're holding no locks here, so our process can be continued before we * actually stop the thread. This is why we need the TDF_STOPPING flag. */ @@ -864,5 +866,7 @@ void proc_continue(proc_t *p) { WITH_PROC_LOCK(p->p_parent) { proc_wakeup_parent(p->p_parent); } - WITH_MTX_LOCK (td->td_lock) { thread_continue(td); } + WITH_MTX_LOCK (td->td_lock) { + thread_continue(td); + } } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 34908768b8..d0e355e434 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -218,8 +218,7 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, if (timeout == 0) { if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { timeout = -1; - } - else { + } else { /* Shortest possible timeout */ timeout = 1; } @@ -246,12 +245,12 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, error = EAGAIN; goto out; } - + if (tsp != NULL && !timevalid) { error = EINVAL; goto out; } - + error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", timeout); if (error == ETIMEDOUT) { @@ -260,18 +259,17 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, } sigset_t unblocked = td->td_sigpend.sp_set; - __sigandset(&waitset, &unblocked) + __sigandset(&waitset, &unblocked); if (__sigfindset(&unblocked)) { error = 0; - } - else { + } else { error = EINTR; } -out: + out: td->td_sigmask = saved_mask; } - + return error; } From c48601522041528acd9d1355a7457e45498af685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Sun, 18 Dec 2022 22:44:11 +0100 Subject: [PATCH 12/35] Revert changes to the build & test infrastructure. --- launch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launch b/launch index 92c68c35ae..bb6c792865 100755 --- a/launch +++ b/launch @@ -121,7 +121,7 @@ CONFIG = { 'drive': 'if=none,id=stick,file={path}', }, 'rpi3': { - 'binary': 'qemu-system-aarch64', + 'binary': 'qemu-mimiker-aarch64', 'options': [ '-machine', 'raspi3b', '-smp', '4', @@ -180,7 +180,7 @@ CONFIG = { 'binary': 'mipsel-mimiker-elf-gdb' }, 'rpi3': { - 'binary': 'gdb-multiarch' + 'binary': 'aarch64-mimiker-elf-gdb' }, 'litex-riscv': { 'binary': 'riscv32-mimiker-elf-gdb' From 7b0199c13ddcf7aa62a9df13eeb0c66696762ddd Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 30 Dec 2022 15:44:41 +0100 Subject: [PATCH 13/35] Sigtimedwait finished --- bin/utest/signal.c | 10 +++------- sys/kern/signal.c | 10 +++++++--- sys/kern/sleepq.c | 3 ++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index d228411a90..055e3b1f27 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -337,9 +337,7 @@ int test_signal_sigtimedwait_timeout(void) { pid_t cpid = fork(); if (cpid == 0) { sched_yield(); - // kill(ppid, SIGCONT); - // sched_yield(); - kill(ppid, SIGUSR1); + kill(ppid, SIGCONT); return 0; } @@ -352,11 +350,9 @@ int test_signal_sigtimedwait_timeout(void) { .tv_sec = 1, }; assert(sigtimedwait(&waitset, &info, &timeout) == -1); + assert(errno == EINTR); + assert(sigtimedwait(&waitset, &info, &timeout) == -1); assert(errno == EAGAIN); - // assert(sigtimedwait(&waitset, &info, &timeout) == -1); - // assert(errno == EINTR); - - assert(sigtimedwait(&waitset, &info, &timeout) == 0); printf("Waiting for child...\n"); int status; diff --git a/sys/kern/signal.c b/sys/kern/signal.c index bff0c5ee68..e1f6ec9a84 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -233,6 +233,8 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, __sigminusset(&cantmask, &waitset); WITH_PROC_LOCK(p) { + /* Unblocking temporarly waited signals so we're woken up upon receiving + * such signal. */ saved_mask = td->td_sigmask; __sigminusset(&waitset, &td->td_sigmask); @@ -259,9 +261,11 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, goto out; } - // sigset_t unblocked = td->td_sigpend.sp_set; - // __sigandset(&waitset, &unblocked); - if ((sig = sig_pending(td))) { + /* We need to find pending signal that we also wait for manually, as + * sig_pending may return a pending signal not from waitset. */ + sigset_t pending = td->td_sigpend.sp_set; + __sigandset(&waitset, &pending); + if ((sig = __sigfindset(&pending))) { sigpend_get(&td->td_sigpend, sig, kinfo); error = 0; } else { diff --git a/sys/kern/sleepq.c b/sys/kern/sleepq.c index 8351b652ea..77f9013fa9 100644 --- a/sys/kern/sleepq.c +++ b/sys/kern/sleepq.c @@ -314,7 +314,8 @@ int sleepq_wait_timed(void *wchan, const void *waitpt, systime_t timeout) { callout_schedule(&td->td_slpcallout, timeout); } - td->td_flags |= (timeout > 0) ? TDF_SLPTIMED : TDF_SLPINTR; + td->td_flags |= TDF_SLPINTR; + td->td_flags |= (timeout > 0) ? TDF_SLPTIMED : 0; sq_enter(td, sc, wchan, waitpt); /* After wakeup, only one of the following flags may be set: From 239ca0eeddbc515849e8eafb935fadcdb7dd52bc Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 30 Dec 2022 15:46:38 +0100 Subject: [PATCH 14/35] format --- sys/kern/main.c | 4 +--- sys/kern/signal.c | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/kern/main.c b/sys/kern/main.c index 1cd9de8d06..5db5c0276f 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -46,9 +46,7 @@ static __noreturn void start_init(__unused void *arg) { thread_t *td = thread_self(); - WITH_MTX_LOCK (td->td_lock) { - sched_set_prio(td, prio_uthread(PRIO_MID)); - } + WITH_MTX_LOCK (td->td_lock) { sched_set_prio(td, prio_uthread(PRIO_MID)); } /* [SECOND_PASS] Init devices that need extra kernel API to be functional. */ init_devices(); diff --git a/sys/kern/signal.c b/sys/kern/signal.c index e1f6ec9a84..8ada2a1859 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -228,15 +228,15 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, } bzero(kinfo, sizeof(*kinfo)); - + /* Silently ignore SIGKILL and SIGSTOP. */ __sigminusset(&cantmask, &waitset); WITH_PROC_LOCK(p) { - /* Unblocking temporarly waited signals so we're woken up upon receiving + /* Unblocking temporarly waited signals so we're woken up upon receiving * such signal. */ saved_mask = td->td_sigmask; - __sigminusset(&waitset, &td->td_sigmask); + __sigminusset(&waitset, &td->td_sigmask); if ((sig = sig_pending(td))) { sigpend_get(&td->td_sigpend, sig, kinfo); From da05dd46ec1782671c981bbc6f7cb8c1bf4d712e Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 30 Dec 2022 15:48:56 +0100 Subject: [PATCH 15/35] Fixed llvm version --- build/tools.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/tools.mk b/build/tools.mk index a6056e6fce..d6fc2586ce 100644 --- a/build/tools.mk +++ b/build/tools.mk @@ -6,7 +6,7 @@ # The following make variables are set by the including makefile: # - TARGET, ABIFLAGS: Set by arch.*.mk files. -LLVM_VER := -13 +LLVM_VER := -14 ifeq ($(shell which ccache > /dev/null; echo $$?), 0) CCACHE := ccache From 54b38ef91611276191a50feff9defce7dd564cf7 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 30 Dec 2022 16:06:36 +0100 Subject: [PATCH 16/35] format --- sys/kern/initrd.c | 4 +++- sys/kern/main.c | 4 +++- sys/kern/proc.c | 8 ++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/kern/initrd.c b/sys/kern/initrd.c index 5148e4116f..b2de15ef36 100644 --- a/sys/kern/initrd.c +++ b/sys/kern/initrd.c @@ -367,7 +367,9 @@ size_t ramdisk_get_size(void) { void ramdisk_dump(void) { cpio_node_t *it; - TAILQ_FOREACH (it, &initrd_head, c_list) { cpio_node_dump(it); } + TAILQ_FOREACH (it, &initrd_head, c_list) { + cpio_node_dump(it); + } } static vfsops_t initrd_vfsops = { diff --git a/sys/kern/main.c b/sys/kern/main.c index 5db5c0276f..1cd9de8d06 100644 --- a/sys/kern/main.c +++ b/sys/kern/main.c @@ -46,7 +46,9 @@ static __noreturn void start_init(__unused void *arg) { thread_t *td = thread_self(); - WITH_MTX_LOCK (td->td_lock) { sched_set_prio(td, prio_uthread(PRIO_MID)); } + WITH_MTX_LOCK (td->td_lock) { + sched_set_prio(td, prio_uthread(PRIO_MID)); + } /* [SECOND_PASS] Init devices that need extra kernel API to be functional. */ init_devices(); diff --git a/sys/kern/proc.c b/sys/kern/proc.c index db45fb5a84..e7d8f9da72 100644 --- a/sys/kern/proc.c +++ b/sys/kern/proc.c @@ -835,7 +835,9 @@ void proc_stop(signo_t sig) { proc_wakeup_parent(p->p_parent); sig_child(p, CLD_STOPPED); } - WITH_MTX_LOCK (td->td_lock) { td->td_flags |= TDF_STOPPING; } + WITH_MTX_LOCK (td->td_lock) { + td->td_flags |= TDF_STOPPING; + } proc_unlock(p); /* We're holding no locks here, so our process can be continued before we * actually stop the thread. This is why we need the TDF_STOPPING flag. */ @@ -864,5 +866,7 @@ void proc_continue(proc_t *p) { WITH_PROC_LOCK(p->p_parent) { proc_wakeup_parent(p->p_parent); } - WITH_MTX_LOCK (td->td_lock) { thread_continue(td); } + WITH_MTX_LOCK (td->td_lock) { + thread_continue(td); + } } From 1994eb2feb668faa70d1f01dd4c5067619366f89 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 30 Dec 2022 16:14:19 +0100 Subject: [PATCH 17/35] Fixed launch changes --- launch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/launch b/launch index 92c68c35ae..bb6c792865 100755 --- a/launch +++ b/launch @@ -121,7 +121,7 @@ CONFIG = { 'drive': 'if=none,id=stick,file={path}', }, 'rpi3': { - 'binary': 'qemu-system-aarch64', + 'binary': 'qemu-mimiker-aarch64', 'options': [ '-machine', 'raspi3b', '-smp', '4', @@ -180,7 +180,7 @@ CONFIG = { 'binary': 'mipsel-mimiker-elf-gdb' }, 'rpi3': { - 'binary': 'gdb-multiarch' + 'binary': 'aarch64-mimiker-elf-gdb' }, 'litex-riscv': { 'binary': 'riscv32-mimiker-elf-gdb' From b301a1c120714a01074f09eb55be425203258c9b Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 1 Jan 2023 14:31:31 +0100 Subject: [PATCH 18/35] Fixed race in timeout test --- bin/utest/signal.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 055e3b1f27..bb8d725abc 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -327,17 +327,25 @@ int test_signal_sigtimedwait(void) { } /* ======= signal_sigtimedwait_timeout ======= */ +static int sigusr2_handled = 0; + +void sigtimedwait_timeout_sigusr2_handler(int signo) { + sigusr2_handled = 1; +} + int test_signal_sigtimedwait_timeout(void) { pid_t ppid = getpid(); signal(SIGCONT, sigcont_handler); + signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler); sigset_t set, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0); pid_t cpid = fork(); if (cpid == 0) { - sched_yield(); - kill(ppid, SIGCONT); + while (!sigusr2_handled) { + kill(ppid, SIGCONT); + } return 0; } @@ -351,6 +359,8 @@ int test_signal_sigtimedwait_timeout(void) { }; assert(sigtimedwait(&waitset, &info, &timeout) == -1); assert(errno == EINTR); + kill(cpid, SIGUSR2); + sleep(1); assert(sigtimedwait(&waitset, &info, &timeout) == -1); assert(errno == EAGAIN); From ac3908b471078af1b14eab070cf066b615f234f7 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 1 Jan 2023 14:39:13 +0100 Subject: [PATCH 19/35] Format. --- bin/utest/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index bb8d725abc..44eb26365a 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -330,7 +330,7 @@ int test_signal_sigtimedwait(void) { static int sigusr2_handled = 0; void sigtimedwait_timeout_sigusr2_handler(int signo) { - sigusr2_handled = 1; + sigusr2_handled = 1; } int test_signal_sigtimedwait_timeout(void) { From 51bbe9f328d64b424e314c005292619704298566 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 1 Jan 2023 18:18:11 +0100 Subject: [PATCH 20/35] Lowered the timeout in signal_sigtimedwait_timeout test. --- bin/utest/signal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 44eb26365a..ae49b4924c 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -354,13 +354,13 @@ int test_signal_sigtimedwait_timeout(void) { __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); timespec_t timeout = { - .tv_nsec = 0, - .tv_sec = 1, + .tv_nsec = 100000000, + .tv_sec = 0, }; assert(sigtimedwait(&waitset, &info, &timeout) == -1); assert(errno == EINTR); kill(cpid, SIGUSR2); - sleep(1); + nanosleep(&timeout, NULL); assert(sigtimedwait(&waitset, &info, &timeout) == -1); assert(errno == EAGAIN); From cbf8c251c0f892b007c2c9292ef8869e8f16c2f1 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sun, 1 Jan 2023 18:38:38 +0100 Subject: [PATCH 21/35] Lower the timeout even more. --- bin/utest/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index ae49b4924c..89e8438cbd 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -354,7 +354,7 @@ int test_signal_sigtimedwait_timeout(void) { __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); timespec_t timeout = { - .tv_nsec = 100000000, + .tv_nsec = 10000000, .tv_sec = 0, }; assert(sigtimedwait(&waitset, &info, &timeout) == -1); From e597ef49de304854e5dc776545c2f037d207dc59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Tue, 3 Jan 2023 19:25:58 +0100 Subject: [PATCH 22/35] Remove sbin/init as it's a part of contrib directory --- Makefile | 2 +- include/sys/syscallargs.h | 1 - sbin/Makefile | 9 ---- sbin/init/LICENSE | 21 --------- sbin/init/Makefile | 6 --- sbin/init/README | 26 ----------- sbin/init/config.h | 5 --- sbin/init/init.8 | 60 -------------------------- sbin/init/init.c | 91 --------------------------------------- 9 files changed, 1 insertion(+), 220 deletions(-) delete mode 100644 sbin/Makefile delete mode 100644 sbin/init/LICENSE delete mode 100644 sbin/init/Makefile delete mode 100644 sbin/init/README delete mode 100644 sbin/init/config.h delete mode 100644 sbin/init/init.8 delete mode 100644 sbin/init/init.c diff --git a/Makefile b/Makefile index ff65e04551..503945af9d 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ TOPDIR = $(CURDIR) # Directories which require calling make recursively -SUBDIR = sys lib bin usr.bin sbin etc include contrib +SUBDIR = sys lib bin usr.bin etc include contrib all: install diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 89cd53a8af..58f7c9b5d1 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -9,7 +9,6 @@ #include #include #include - #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } diff --git a/sbin/Makefile b/sbin/Makefile deleted file mode 100644 index 499be24f06..0000000000 --- a/sbin/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# vim: tabstop=8 shiftwidth=8 noexpandtab: - -TOPDIR = $(realpath ..) - -SUBDIR = init - -all: build - -include $(TOPDIR)/build/common.mk diff --git a/sbin/init/LICENSE b/sbin/init/LICENSE deleted file mode 100644 index 91b577935b..0000000000 --- a/sbin/init/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT/X Consortium License - -© 2014-2015 Dimitris Papastamos - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/sbin/init/Makefile b/sbin/init/Makefile deleted file mode 100644 index aaf2853bcc..0000000000 --- a/sbin/init/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -TOPDIR = $(realpath ../..) - -PROGRAM = init -FORMAT-EXCLUDE = $(SOURCES) - -include $(TOPDIR)/build/build.prog.mk diff --git a/sbin/init/README b/sbin/init/README deleted file mode 100644 index 13642b83a1..0000000000 --- a/sbin/init/README +++ /dev/null @@ -1,26 +0,0 @@ -sinit - suckless init -===================== - -sinit is a simple init. It was initially based on -Rich Felker's minimal init[1]. - -Why? ----- - -I wanted to get rid of Busybox init on my toy distro[2]. - -How? ----- - -There are 3 signals that sinit will act on. - - SIGUSR1: powers off the machine. - SIGINT: reboots the machine (or alternatively via ctrl-alt-del). - SIGCHLD: reap children - -To see how sinit integrates with the init scripts, then have -a look at [3]. - -[1] https://gist.github.com/rofl0r/6168719 -[2] http://git.2f30.org/morpheus/ -[3] http://git.2f30.org/ports/tree/fs/ diff --git a/sbin/init/config.h b/sbin/init/config.h deleted file mode 100644 index 3d2da6fcb6..0000000000 --- a/sbin/init/config.h +++ /dev/null @@ -1,5 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -static char *const rcinitcmd[] = { "/etc/rc.init", NULL }; -static char *const rcrebootcmd[] = { "/etc/rc.shutdown", "reboot", NULL }; -static char *const rcpoweroffcmd[] = { "/etc/rc.shutdown", "poweroff", NULL }; diff --git a/sbin/init/init.8 b/sbin/init/init.8 deleted file mode 100644 index 605b457bd2..0000000000 --- a/sbin/init/init.8 +++ /dev/null @@ -1,60 +0,0 @@ -.Dd December 4, 2014 -.Dt SINIT 8 sinit\-1.1 -.Os -.Sh NAME -.Nm sinit -.Nd simple init -.Sh DESCRIPTION -.Nm -is a simple init. It is configured by modifying -.Dq config.h -and recompiling the code. -.Ss Init sequence -By default -.Nm -will execute -.Dq /bin/rc.init . -You can chain your init scripts together at that point to allow for -single-user and multi-user operation. -.Ss Signal handling -.Nm -will respond to the following signals: -.Bl -tag -width xxxxxxxx -.It USR1 -Default action is to initiate the shutdown sequence by -executing -.Dq /bin/rc.shutdown poweroff . -.It INT -Default action is to initiate the reboot sequence by -executing -.Dq /bin/rc.shutdown reboot . -.It CHLD -Reap children. -.El -.Ss General considerations -Running the -.Dq rc.shutdown -script directly is not recommended. If any -process in your session has stale filesystem references then it is -likely your init scripts will fail to unmount the filesystem cleanly. -It is recommended to signal -.Nm -via a wrapper script. -.Pp -.Nm -does not clear utmp records. The version of -.Xr getty 8 -in ubase clears the utmp entries on the specified tty before it -spawns the given program, usually -.Xr login 1 . -.Pp -.Nm -does not restart -.Xr getty 8 -or interact with it in any way. You will need an external -respawning mechanism to restart it. -.Sh SEE ALSO -.Xr getty 8 , -.Xr killall5 8 -.Sh AUTHORS -.An Dimitris Papastamos Aq Mt sin@2f30.org . diff --git a/sbin/init/init.c b/sbin/init/init.c deleted file mode 100644 index 716671087f..0000000000 --- a/sbin/init/init.c +++ /dev/null @@ -1,91 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include - -#include -#include -#include -#include - -#define LEN(x) (sizeof (x) / sizeof *(x)) -#define TIMEO 30 - -static void sigpoweroff(void); -static void sigreap(void); -static void sigreboot(void); -static void spawn(char *const []); - -static struct { - int sig; - void (*handler)(void); -} sigmap[] = { - { SIGUSR1, sigpoweroff }, - { SIGCHLD, sigreap }, - { SIGALRM, sigreap }, - { SIGINT, sigreboot }, -}; - -#include "config.h" - -static sigset_t set; - -int -main(void) -{ - int sig; - size_t i; - - if (getpid() != 1) - return 1; - chdir("/"); - sigfillset(&set); - sigprocmask(SIG_BLOCK, &set, NULL); - spawn(rcinitcmd); - while (1) { - alarm(TIMEO); - sigwait(&set, &sig); - for (i = 0; i < LEN(sigmap); i++) { - if (sigmap[i].sig == sig) { - sigmap[i].handler(); - break; - } - } - } - /* not reachable */ - return 0; -} - -static void -sigpoweroff(void) -{ - spawn(rcpoweroffcmd); -} - -static void -sigreap(void) -{ - while (waitpid(-1, NULL, WNOHANG) > 0) - ; - alarm(TIMEO); -} - -static void -sigreboot(void) -{ - spawn(rcrebootcmd); -} - -static void -spawn(char *const argv[]) -{ - switch (fork()) { - case 0: - sigprocmask(SIG_UNBLOCK, &set, NULL); - setsid(); - execvp(argv[0], argv); - perror("execvp"); - _exit(1); - case -1: - perror("fork"); - } -} From 76ca8f154df0cc9a0040961c74ef467bd3ad762e Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 12 Jan 2023 17:34:52 +0100 Subject: [PATCH 23/35] Use new utest interface for sigtimedwait tests. --- bin/utest/signal.c | 4 ++-- sys/kern/signal.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 25c73d840b..5f7b38ea52 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -297,7 +297,7 @@ TEST_ADD(signal_sigsuspend) { } /* ======= signal_sigtimedwait ======= */ -int test_signal_sigtimedwait(void) { +TEST_ADD(signal_sigtimedwait) { pid_t ppid = getpid(); signal(SIGCONT, sigcont_handler); sigset_t set, current, waitset; @@ -339,7 +339,7 @@ void sigtimedwait_timeout_sigusr2_handler(int signo) { sigusr2_handled = 1; } -int test_signal_sigtimedwait_timeout(void) { +TEST_ADD(signal_sigtimedwait_timeout) { pid_t ppid = getpid(); signal(SIGCONT, sigcont_handler); signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler); diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 226b6a968d..b459e283e0 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -253,7 +253,8 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, goto out; } - error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", &p->p_lock, timeout); + error = + sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", &p->p_lock, timeout); if (error == ETIMEDOUT) { error = EAGAIN; From c576c7399039da256c6fe93323b0eb857b0f35f3 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 12 Jan 2023 18:05:08 +0100 Subject: [PATCH 24/35] Use new utest util macros. --- bin/utest/signal.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 5f7b38ea52..ffa717fd59 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -346,7 +346,7 @@ TEST_ADD(signal_sigtimedwait_timeout) { sigset_t set, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); - assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0); + syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); pid_t cpid = fork(); if (cpid == 0) { while (!sigusr2_handled) { @@ -363,12 +363,10 @@ TEST_ADD(signal_sigtimedwait_timeout) { .tv_nsec = 10000000, .tv_sec = 0, }; - assert(sigtimedwait(&waitset, &info, &timeout) == -1); - assert(errno == EINTR); + syscall_fail(sigtimedwait(&waitset, &info, &timeout), EINTR); kill(cpid, SIGUSR2); nanosleep(&timeout, NULL); - assert(sigtimedwait(&waitset, &info, &timeout) == -1); - assert(errno == EAGAIN); + syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); printf("Waiting for child...\n"); int status; From db00050ff50bcf2e7cd0efc598c63a635952ada7 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 12 Jan 2023 18:38:54 +0100 Subject: [PATCH 25/35] Check only for waited signals in the pending mask. --- sys/kern/signal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/kern/signal.c b/sys/kern/signal.c index b459e283e0..838ffd1def 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -239,7 +239,9 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, saved_mask = td->td_sigmask; __sigminusset(&waitset, &td->td_sigmask); - if ((sig = sig_pending(td))) { + sigset_t pending = td->td_sigpend.sp_set; + __sigandset(&waitset, &pending); + if ((sig = __sigfindset(&pending))) { sigpend_get(&td->td_sigpend, sig, kinfo); error = 0; goto out; @@ -263,7 +265,7 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, /* We need to find pending signal that we also wait for manually, as * sig_pending may return a pending signal not from waitset. */ - sigset_t pending = td->td_sigpend.sp_set; + pending = td->td_sigpend.sp_set; __sigandset(&waitset, &pending); if ((sig = __sigfindset(&pending))) { sigpend_get(&td->td_sigpend, sig, kinfo); From 4088dd64d347364776606e672d96b8f920ba4167 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 13 Jan 2023 11:59:46 +0100 Subject: [PATCH 26/35] Handle bad timeout format. --- bin/utest/signal.c | 24 +++++++++++++++++------- sys/kern/signal.c | 30 ++++++++++++++++++------------ 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index ffa717fd59..beea5fcec9 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -304,13 +304,10 @@ TEST_ADD(signal_sigtimedwait) { __sigemptyset(&set); __sigaddset(&set, SIGUSR1); __sigaddset(&set, SIGCONT); - assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0); + syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); pid_t cpid = fork(); if (cpid == 0) { - // for (int i = 0; i < 10; i++) { - // kill(ppid, SIGCONT); - // } - // sched_yield(); + sched_yield(); kill(ppid, SIGUSR1); return 0; } @@ -360,10 +357,23 @@ TEST_ADD(signal_sigtimedwait_timeout) { __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); timespec_t timeout = { - .tv_nsec = 10000000, - .tv_sec = 0, + .tv_nsec = -1, + .tv_sec = -1, }; + + /* tv_nsec is invalid. */ + syscall_fail(sigtimedwait(&waitset, &info, &timeout), EINVAL); + + /* tv_nsec is valid, but tv_sec < 0. */ + timeout.tv_nsec = 10000000; + syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); + + /* Timeout is valid, should be interrupted. */ + timeout.tv_sec = 0; syscall_fail(sigtimedwait(&waitset, &info, &timeout), EINTR); + + /* After the signal we should be interrupted only once, so next call to + * sigtimedwait will timeout. */ kill(cpid, SIGUSR2); nanosleep(&timeout, NULL); syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 838ffd1def..cc86fd8b3f 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -212,18 +212,24 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, thread_t *td = p->p_thread; if (tsp != NULL) { - if (tsp->tv_nsec >= 0 && tsp->tv_nsec < 1000000000) { - timevalid = 1; - timeout = ts2hz(tsp); - /* Timeout set to 0 means to not block, but for sleepq it means to - * wait indefinitely */ - if (timeout == 0) { - if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { - timeout = -1; - } else { - /* Shortest possible timeout */ - timeout = 1; - } + if (tsp->tv_nsec < 0 || tsp->tv_nsec >= 1000000000) { + return EINVAL; + } + /* This is the same behaviour as in OpenBSD. */ + if (tsp->tv_sec < 0) { + return EAGAIN; + } + + timevalid = 1; + timeout = ts2hz(tsp); + /* Timeout set to 0 means to not block, but for sleepq it means to + * wait indefinitely */ + if (timeout == 0) { + if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { + timeout = -1; + } else { + /* Shortest possible timeout */ + timeout = 1; } } } From cdfc49309d20ef621b8167dba2a2a5ec76c2fd59 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 13 Jan 2023 12:56:27 +0100 Subject: [PATCH 27/35] Remove printf's from test, assert on all syscalls. --- bin/utest/signal.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index beea5fcec9..9e4384a5e5 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -299,31 +299,31 @@ TEST_ADD(signal_sigsuspend) { /* ======= signal_sigtimedwait ======= */ TEST_ADD(signal_sigtimedwait) { pid_t ppid = getpid(); - signal(SIGCONT, sigcont_handler); + syscall_ok(signal(SIGCONT, sigcont_handler)); sigset_t set, current, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); __sigaddset(&set, SIGCONT); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); pid_t cpid = fork(); + assert(cpid >= 0); if (cpid == 0) { sched_yield(); - kill(ppid, SIGUSR1); + syscall_ok(kill(ppid, SIGUSR1)); return 0; } - printf("Calling sigtimedwait()...\n"); siginfo_t info; __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); assert(sigtimedwait(&waitset, &info, NULL) == SIGUSR1); assert(info.si_signo == SIGUSR1); - sigprocmask(SIG_BLOCK, NULL, ¤t); + + syscall_ok(sigprocmask(SIG_BLOCK, NULL, ¤t)); assert(__sigsetequal(&set, ¤t)); - printf("Waiting for child...\n"); int status; - wait(&status); + assert(wait(&status) == cpid); assert(WIFEXITED(status)); assert(WEXITSTATUS(status) == 0); return 0; @@ -338,13 +338,15 @@ void sigtimedwait_timeout_sigusr2_handler(int signo) { TEST_ADD(signal_sigtimedwait_timeout) { pid_t ppid = getpid(); - signal(SIGCONT, sigcont_handler); - signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler); + syscall_ok(signal(SIGCONT, sigcont_handler)); + syscall_ok(signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler)); sigset_t set, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); + pid_t cpid = fork(); + assert(cpid >= 0); if (cpid == 0) { while (!sigusr2_handled) { kill(ppid, SIGCONT); @@ -352,7 +354,6 @@ TEST_ADD(signal_sigtimedwait_timeout) { return 0; } - printf("Calling sigtimedwait()...\n"); siginfo_t info; __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); @@ -374,13 +375,14 @@ TEST_ADD(signal_sigtimedwait_timeout) { /* After the signal we should be interrupted only once, so next call to * sigtimedwait will timeout. */ - kill(cpid, SIGUSR2); + syscall_ok(kill(cpid, SIGUSR2)); + + /* This may be woken up by a timeout or by an interrupt. */ nanosleep(&timeout, NULL); syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); - printf("Waiting for child...\n"); int status; - wait(&status); + assert(wait(&status) == cpid); assert(WIFEXITED(status)); assert(WEXITSTATUS(status) == 0); return 0; From f7977d59abd96a10695c3f6d3ac30cd8e7dce7f3 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Sat, 14 Jan 2023 16:26:42 +0100 Subject: [PATCH 28/35] Use utest_spawn and utest_child_exited --- bin/utest/signal.c | 45 ++++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 9e4384a5e5..5a3e2d0da5 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -297,21 +297,22 @@ TEST_ADD(signal_sigsuspend) { } /* ======= signal_sigtimedwait ======= */ +int sigtimedwait_child(void *arg) { + pid_t ppid = getppid(); + sched_yield(); + syscall_ok(kill(ppid, SIGUSR1)); + return 0; +} + TEST_ADD(signal_sigtimedwait) { - pid_t ppid = getpid(); syscall_ok(signal(SIGCONT, sigcont_handler)); sigset_t set, current, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); __sigaddset(&set, SIGCONT); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); - pid_t cpid = fork(); - assert(cpid >= 0); - if (cpid == 0) { - sched_yield(); - syscall_ok(kill(ppid, SIGUSR1)); - return 0; - } + + utest_spawn(sigtimedwait_child, NULL); siginfo_t info; __sigemptyset(&waitset); @@ -322,10 +323,7 @@ TEST_ADD(signal_sigtimedwait) { syscall_ok(sigprocmask(SIG_BLOCK, NULL, ¤t)); assert(__sigsetequal(&set, ¤t)); - int status; - assert(wait(&status) == cpid); - assert(WIFEXITED(status)); - assert(WEXITSTATUS(status) == 0); + utest_child_exited(0); return 0; } @@ -336,8 +334,15 @@ void sigtimedwait_timeout_sigusr2_handler(int signo) { sigusr2_handled = 1; } +int sigtimedwait_timeout_child(void *arg) { + ppid = getppid(); + while (!sigusr2_handled) { + kill(ppid, SIGCONT); + } + return 0; +} + TEST_ADD(signal_sigtimedwait_timeout) { - pid_t ppid = getpid(); syscall_ok(signal(SIGCONT, sigcont_handler)); syscall_ok(signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler)); sigset_t set, waitset; @@ -345,14 +350,7 @@ TEST_ADD(signal_sigtimedwait_timeout) { __sigaddset(&set, SIGUSR1); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); - pid_t cpid = fork(); - assert(cpid >= 0); - if (cpid == 0) { - while (!sigusr2_handled) { - kill(ppid, SIGCONT); - } - return 0; - } + pid_t cpid = utest_spawn(sigtimedwait_timeout_child, NULL); siginfo_t info; __sigemptyset(&waitset); @@ -381,10 +379,7 @@ TEST_ADD(signal_sigtimedwait_timeout) { nanosleep(&timeout, NULL); syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); - int status; - assert(wait(&status) == cpid); - assert(WIFEXITED(status)); - assert(WEXITSTATUS(status) == 0); + utest_child_exited(0); return 0; } From 97d0591badc77895a56aef90eef48bfb5f2d8adf Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 19 Jan 2023 14:47:02 +0100 Subject: [PATCH 29/35] Clean up do_sigtimedwait --- include/sys/syscallargs.h | 1 + sys/kern/signal.c | 35 ++++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/sys/syscallargs.h b/include/sys/syscallargs.h index 58f7c9b5d1..89cd53a8af 100644 --- a/include/sys/syscallargs.h +++ b/include/sys/syscallargs.h @@ -9,6 +9,7 @@ #include #include #include + #define SCARG(p, x) ((p)->x.arg) #define SYSCALLARG(x) union { register_t _pad; x arg; } diff --git a/sys/kern/signal.c b/sys/kern/signal.c index cc86fd8b3f..10099660c3 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -204,26 +204,35 @@ int do_sigsuspend(proc_t *p, const sigset_t *mask) { return ERESTARTNOHAND; } -int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi, timespec_t *tsp) { - int timevalid = 0, error = 0, timeout = 0; + int error = 0, timeout = 0; sigset_t saved_mask; signo_t sig; thread_t *td = p->p_thread; + /* + * Calculate timeout based on tsp. + * + * NULL pointer means an infinite timeout. + * {.tv_sec = 0, .tv_nsec = 0} means to not block. + * Timeout is valid only if 0 <= tv_nsec <= 1e9. If this is not true, + * immediately return EINVAL. If tv_sec < 0 immediately return EAGAIN. + * + * We set the timeout value such that: + * - timeout == -1: do not block + * - timeout == 0: wait indefinitely + * - timeout > 0: wait for timeout. + */ if (tsp != NULL) { if (tsp->tv_nsec < 0 || tsp->tv_nsec >= 1000000000) { return EINVAL; } - /* This is the same behaviour as in OpenBSD. */ if (tsp->tv_sec < 0) { return EAGAIN; } - timevalid = 1; timeout = ts2hz(tsp); - /* Timeout set to 0 means to not block, but for sleepq it means to - * wait indefinitely */ if (timeout == 0) { if (tsp->tv_nsec == 0 && tsp->tv_sec == 0) { timeout = -1; @@ -234,7 +243,7 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, } } - bzero(kinfo, sizeof(*kinfo)); + bzero(ksi, sizeof(*ksi)); /* Silently ignore SIGKILL and SIGSTOP. */ __sigminusset(&cantmask, &waitset); @@ -245,10 +254,12 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, saved_mask = td->td_sigmask; __sigminusset(&waitset, &td->td_sigmask); + /* We need to find pending signal that we also wait for manually, as + * sig_pending may return a pending signal not from waitset. */ sigset_t pending = td->td_sigpend.sp_set; __sigandset(&waitset, &pending); if ((sig = __sigfindset(&pending))) { - sigpend_get(&td->td_sigpend, sig, kinfo); + sigpend_get(&td->td_sigpend, sig, ksi); error = 0; goto out; } @@ -256,10 +267,6 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, error = EAGAIN; goto out; } - if (tsp != NULL && !timevalid) { - error = EINVAL; - goto out; - } error = sleepq_wait_timed(&td->td_sigmask, "sigtimedwait()", &p->p_lock, timeout); @@ -269,12 +276,10 @@ int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, goto out; } - /* We need to find pending signal that we also wait for manually, as - * sig_pending may return a pending signal not from waitset. */ pending = td->td_sigpend.sp_set; __sigandset(&waitset, &pending); if ((sig = __sigfindset(&pending))) { - sigpend_get(&td->td_sigpend, sig, kinfo); + sigpend_get(&td->td_sigpend, sig, ksi); error = 0; } else { error = EINTR; From f9014c9abf3d317934a064e557a30060fa8f518e Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Thu, 19 Jan 2023 15:37:12 +0100 Subject: [PATCH 30/35] Refactor tests --- bin/utest/signal.c | 63 ++++++++++++++++++++++++++++++---------------- sys/tests/utest.c | 1 + 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 5a3e2d0da5..66d092a346 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -299,7 +299,6 @@ TEST_ADD(signal_sigsuspend) { /* ======= signal_sigtimedwait ======= */ int sigtimedwait_child(void *arg) { pid_t ppid = getppid(); - sched_yield(); syscall_ok(kill(ppid, SIGUSR1)); return 0; } @@ -328,30 +327,20 @@ TEST_ADD(signal_sigtimedwait) { } /* ======= signal_sigtimedwait_timeout ======= */ -static int sigusr2_handled = 0; - -void sigtimedwait_timeout_sigusr2_handler(int signo) { - sigusr2_handled = 1; -} - int sigtimedwait_timeout_child(void *arg) { ppid = getppid(); - while (!sigusr2_handled) { - kill(ppid, SIGCONT); - } + kill(ppid, SIGUSR1); + kill(ppid, SIGCONT); return 0; } TEST_ADD(signal_sigtimedwait_timeout) { syscall_ok(signal(SIGCONT, sigcont_handler)); - syscall_ok(signal(SIGUSR2, sigtimedwait_timeout_sigusr2_handler)); sigset_t set, waitset; __sigemptyset(&set); __sigaddset(&set, SIGUSR1); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); - pid_t cpid = utest_spawn(sigtimedwait_timeout_child, NULL); - siginfo_t info; __sigemptyset(&waitset); __sigaddset(&waitset, SIGUSR1); @@ -367,18 +356,50 @@ TEST_ADD(signal_sigtimedwait_timeout) { timeout.tv_nsec = 10000000; syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); - /* Timeout is valid, should be interrupted. */ timeout.tv_sec = 0; - syscall_fail(sigtimedwait(&waitset, &info, &timeout), EINTR); + /* Should timeout. */ + syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); - /* After the signal we should be interrupted only once, so next call to - * sigtimedwait will timeout. */ - syscall_ok(kill(cpid, SIGUSR2)); + utest_spawn(sigtimedwait_timeout_child, NULL); - /* This may be woken up by a timeout or by an interrupt. */ - nanosleep(&timeout, NULL); - syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); + /* If we handled sigcont, then SIGUSR1 must be pending. */ + while (!sigcont_handled) + sched_yield(); + + /* Should not block, but receive the signal as it is in the pending mask. */ + timeout.tv_nsec = 0; + assert(sigtimedwait(&waitset, &info, &timeout) == SIGUSR1); + assert(info.si_signo == SIGUSR1); + + utest_child_exited(0); + return 0; +} + +/* ======= signal_sigtimedwait_intr ====== */ +int sigtimedwait_intr_child(void *arg) { + pid_t ppid = getppid(); + while (!sigcont_handled) { + kill(ppid, SIGCONT); + } + return 0; +} + +TEST_ADD(signal_sigtimedwait_intr) { + syscall_ok(signal(SIGCONT, sigcont_handler)); + sigset_t set, waitset; + __sigemptyset(&set); + __sigaddset(&set, SIGUSR1); + syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); + + siginfo_t info; + __sigemptyset(&waitset); + __sigaddset(&waitset, SIGUSR1); + + pid_t cpid = utest_spawn(sigtimedwait_intr_child, NULL); + + syscall_fail(sigtimedwait(&waitset, &info, NULL), EINTR); + syscall_ok(kill(cpid, SIGCONT)); utest_child_exited(0); return 0; } diff --git a/sys/tests/utest.c b/sys/tests/utest.c index ab437f6ae6..8d59965839 100644 --- a/sys/tests/utest.c +++ b/sys/tests/utest.c @@ -105,6 +105,7 @@ UTEST_ADD(signal_mask); UTEST_ADD(signal_mask_nonmaskable); UTEST_ADD(signal_sigtimedwait); UTEST_ADD(signal_sigtimedwait_timeout); +UTEST_ADD(signal_sigtimedwait_intr); UTEST_ADD(signal_sigsuspend); UTEST_ADD(signal_sigsuspend_stop); UTEST_ADD(signal_handler_mask); From a5fb8739c215bd6a83ceec25abc441405e9a0895 Mon Sep 17 00:00:00 2001 From: Franciszek Malinka Date: Fri, 20 Jan 2023 10:20:28 +0100 Subject: [PATCH 31/35] Tidy up --- sys/kern/signal.c | 4 ++-- sys/kern/syscalls.c | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sys/kern/signal.c b/sys/kern/signal.c index 10099660c3..0b30668474 100644 --- a/sys/kern/signal.c +++ b/sys/kern/signal.c @@ -13,8 +13,8 @@ #include #include -#include "sys/siginfo.h" -#include "sys/sigtypes.h" +#include +#include static KMALLOC_DEFINE(M_SIGNAL, "signal"); diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 498f668d96..652f1e4bbc 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1334,14 +1334,12 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, siginfo_t *u_info = SCARG(args, info); const timespec_t *u_timeout = SCARG(args, timeout); sigset_t set; - ksiginfo_t kinfo; + ksiginfo_t ksi; timespec_t timeout = {}; - timespec_t *tsp = NULL; int error; if (u_timeout) { error = copyin_s(u_timeout, timeout); - tsp = &timeout; if (error) return error; } @@ -1350,14 +1348,14 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, if (error) return error; - error = do_sigtimedwait(p, set, &kinfo, tsp); + error = do_sigtimedwait(p, set, &ksi, u_timeout ? &timeout : NULL); if (error) return error; if (u_info) { - error = copyout_s(kinfo.ksi_info, u_info); + error = copyout_s(ksi.ksi_info, u_info); } - *res = kinfo.ksi_info.si_signo; + *res = ksi.ksi_info.si_signo; return error; } From 3c7670deb02c40f67d36fdd104cbb3f28d56fac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Wed, 14 Jun 2023 22:45:46 +0200 Subject: [PATCH 32/35] Address some long standing remarks (pt. 1) --- bin/utest/signal.c | 72 +++++++++++++++++++------------------- bin/utest/util.c | 4 +-- bin/utest/util.h | 4 +++ include/sys/sigtypes.h | 4 +++ lib/libc/gen/sigismember.c | 10 ++++++ sys/kern/syscalls.c | 4 +-- 6 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 lib/libc/gen/sigismember.c diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 66d092a346..689d942d2a 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -159,7 +159,7 @@ TEST_ADD(signal_cont_masked) { if (pid == 0) { /* Block SIGCONT. */ sigset_t mask, old; - __sigemptyset(&mask); + sigemptyset(&mask); sigaddset(&mask, SIGCONT); assert(sigprocmask(SIG_BLOCK, &mask, &old) == 0); /* Even though SIGCONT is blocked, it should wake us up, but it @@ -218,7 +218,7 @@ TEST_ADD(signal_mask) { do { sched_yield(); sigpending(&set); - } while (!__sigismember(&set, SIGCONT)); + } while (!sigismember(&set, SIGCONT)); assert(!sigcont_handled); @@ -238,15 +238,15 @@ TEST_ADD(signal_mask) { /* ======= signal_mask_nonmaskable ======= */ TEST_ADD(signal_mask_nonmaskable) { sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGSTOP); - __sigaddset(&set, SIGKILL); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGSTOP); + sigaddset(&set, SIGKILL); + sigaddset(&set, SIGUSR1); /* The call should succeed, but SIGKILL and SIGSTOP shouldn't be blocked. */ assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); assert(sigprocmask(SIG_BLOCK, NULL, &set) == 0); - __sigaddset(&old, SIGUSR1); - assert(__sigsetequal(&set, &old)); + sigaddset(&old, SIGUSR1); + assert(sigsetequal(&set, &old)); return 0; } @@ -256,11 +256,11 @@ TEST_ADD(signal_sigsuspend) { signal(SIGCONT, sigcont_handler); signal(SIGUSR1, sigusr1_handler); sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGCONT); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGCONT); + sigaddset(&set, SIGUSR1); assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); - __sigaddset(&old, SIGCONT); + sigaddset(&old, SIGCONT); pid_t cpid = fork(); if (cpid == 0) { for (int i = 0; i < 10; i++) { @@ -274,17 +274,17 @@ TEST_ADD(signal_sigsuspend) { printf("Calling sigsuspend()...\n"); sigset_t current; sigprocmask(SIG_BLOCK, NULL, ¤t); - assert(__sigismember(¤t, SIGUSR1)); - assert(!__sigismember(&old, SIGUSR1)); + assert(sigismember(¤t, SIGUSR1)); + assert(!sigismember(&old, SIGUSR1)); sigsuspend(&old); /* Check if mask is set back after waking up */ sigprocmask(SIG_BLOCK, NULL, &set); - assert(__sigsetequal(&set, ¤t)); + assert(sigsetequal(&set, ¤t)); /* SIGUSR1 should have woken us up, but SIGCONT should still be pending. */ assert(sigusr1_handled); assert(!sigcont_handled); - __sigemptyset(&set); - __sigaddset(&set, SIGCONT); + sigemptyset(&set); + sigaddset(&set, SIGCONT); assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0); assert(sigcont_handled); @@ -297,7 +297,7 @@ TEST_ADD(signal_sigsuspend) { } /* ======= signal_sigtimedwait ======= */ -int sigtimedwait_child(void *arg) { +static int sigtimedwait_child(__unused void *arg) { pid_t ppid = getppid(); syscall_ok(kill(ppid, SIGUSR1)); return 0; @@ -306,21 +306,21 @@ int sigtimedwait_child(void *arg) { TEST_ADD(signal_sigtimedwait) { syscall_ok(signal(SIGCONT, sigcont_handler)); sigset_t set, current, waitset; - __sigemptyset(&set); - __sigaddset(&set, SIGUSR1); - __sigaddset(&set, SIGCONT); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + sigaddset(&set, SIGCONT); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); utest_spawn(sigtimedwait_child, NULL); siginfo_t info; - __sigemptyset(&waitset); - __sigaddset(&waitset, SIGUSR1); + sigemptyset(&waitset); + sigaddset(&waitset, SIGUSR1); assert(sigtimedwait(&waitset, &info, NULL) == SIGUSR1); assert(info.si_signo == SIGUSR1); syscall_ok(sigprocmask(SIG_BLOCK, NULL, ¤t)); - assert(__sigsetequal(&set, ¤t)); + assert(sigsetequal(&set, ¤t)); utest_child_exited(0); return 0; @@ -337,13 +337,13 @@ int sigtimedwait_timeout_child(void *arg) { TEST_ADD(signal_sigtimedwait_timeout) { syscall_ok(signal(SIGCONT, sigcont_handler)); sigset_t set, waitset; - __sigemptyset(&set); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); siginfo_t info; - __sigemptyset(&waitset); - __sigaddset(&waitset, SIGUSR1); + sigemptyset(&waitset); + sigaddset(&waitset, SIGUSR1); timespec_t timeout = { .tv_nsec = -1, .tv_sec = -1, @@ -387,13 +387,13 @@ int sigtimedwait_intr_child(void *arg) { TEST_ADD(signal_sigtimedwait_intr) { syscall_ok(signal(SIGCONT, sigcont_handler)); sigset_t set, waitset; - __sigemptyset(&set); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); siginfo_t info; - __sigemptyset(&waitset); - __sigaddset(&waitset, SIGUSR1); + sigemptyset(&waitset); + sigaddset(&waitset, SIGUSR1); pid_t cpid = utest_spawn(sigtimedwait_intr_child, NULL); @@ -409,8 +409,8 @@ TEST_ADD(signal_sigsuspend_stop) { pid_t ppid = getpid(); signal(SIGUSR1, sigusr1_handler); sigset_t set, old; - __sigemptyset(&set); - __sigaddset(&set, SIGUSR1); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); pid_t cpid = fork(); if (cpid == 0) { @@ -487,8 +487,8 @@ TEST_ADD(signal_handler_mask) { pid_t ppid = getpid(); struct sigaction sa = {.sa_handler = yield_handler, .sa_flags = 0}; /* Block SIGUSR1 when executing handler for SIGUSR2. */ - __sigemptyset(&sa.sa_mask); - __sigaddset(&sa.sa_mask, SIGUSR1); + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGUSR1); assert(sigaction(SIGUSR2, &sa, NULL) == 0); signal(SIGUSR1, sigusr1_handler); signal(SIGCONT, sigcont_handler); diff --git a/bin/utest/util.c b/bin/utest/util.c index a13402af37..fc99c83ff7 100644 --- a/bin/utest/util.c +++ b/bin/utest/util.c @@ -50,14 +50,14 @@ static void noop_handler(int signo) { void signal_setup(int signo) { signal(signo, noop_handler); sigset_t mask; - __sigemptyset(&mask); + sigemptyset(&mask); sigaddset(&mask, signo); assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0); } void wait_for_signal(int signo) { sigset_t mask; - __sigfillset(&mask); + sigfillset(&mask); sigdelset(&mask, signo); sigsuspend(&mask); } diff --git a/bin/utest/util.h b/bin/utest/util.h index 0858e15dbe..7bc60d32d1 100644 --- a/bin/utest/util.h +++ b/bin/utest/util.h @@ -6,6 +6,10 @@ #include #include +static inline int sigsetequal(sigset_t *a, sigset_t *b) { + return memcmp(a, b, sizeof(sigset_t)) == 0; +} + /* Wait for a single child process with process id `pid` to exit, * and check that its exit code matches the expected value. */ void wait_for_child_exit(int pid, int exit_code); diff --git a/include/sys/sigtypes.h b/include/sys/sigtypes.h index 36c04d467c..8766f37c29 100644 --- a/include/sys/sigtypes.h +++ b/include/sys/sigtypes.h @@ -15,6 +15,8 @@ typedef struct { uint32_t __bits; /* bit 0 is unused */ } sigset_t; +#if defined(_KERNEL) || defined(_LIBC) + /* * Macro for manipulating signal masks. */ @@ -33,6 +35,8 @@ typedef struct { { (t)->__bits &= (s)->__bits; } #define __sigfindset(s) (__builtin_ffs((s)->__bits)) +#endif /* !_KERNEL */ + typedef struct sigaltstack { void *ss_sp; /* signal stack base */ size_t ss_size; /* signal stack length */ diff --git a/lib/libc/gen/sigismember.c b/lib/libc/gen/sigismember.c new file mode 100644 index 0000000000..0a38aa5f14 --- /dev/null +++ b/lib/libc/gen/sigismember.c @@ -0,0 +1,10 @@ +#include +#include + +int sigismember(const sigset_t *set, int signo) { + if (signo <= 0 || signo >= NSIG) { + errno = EINVAL; + return -1; + } + return (__sigismember(set, signo)); +} diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 50f09a19d1..53905f5222 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1355,9 +1355,9 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, if (error) return error; - if (u_info) { + if (u_info) error = copyout_s(ksi.ksi_info, u_info); - } + *res = ksi.ksi_info.si_signo; return error; From 4b8edb819147eb441a98da494849c22b6ee1e1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Wed, 14 Jun 2023 22:48:30 +0200 Subject: [PATCH 33/35] Address some long lasting remarks (pt. 2) --- bin/utest/signal.c | 2 +- include/sys/signal.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 689d942d2a..f197b040db 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -327,7 +327,7 @@ TEST_ADD(signal_sigtimedwait) { } /* ======= signal_sigtimedwait_timeout ======= */ -int sigtimedwait_timeout_child(void *arg) { +static int sigtimedwait_timeout_child(__unused void *arg) { ppid = getppid(); kill(ppid, SIGUSR1); kill(ppid, SIGCONT); diff --git a/include/sys/signal.h b/include/sys/signal.h index 8df28968e4..7077d24d7a 100644 --- a/include/sys/signal.h +++ b/include/sys/signal.h @@ -202,10 +202,8 @@ void sig_onexec(proc_t *p); int do_sigaction(signo_t sig, const sigaction_t *act, sigaction_t *oldact); int do_sigprocmask(int how, const sigset_t *set, sigset_t *oset); int do_sigsuspend(proc_t *p, const sigset_t *mask); -int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, - struct timespec *timeout); int do_sigpending(proc_t *p, sigset_t *set); -int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *kinfo, +int do_sigtimedwait(proc_t *p, sigset_t waitset, ksiginfo_t *ksi, struct timespec *timeout); #endif /* !_KERNEL */ From 65da74edc2b3270327b6ffcf3668cf30bc2e13d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Thu, 15 Jun 2023 19:03:28 +0200 Subject: [PATCH 34/35] Address some long lasting remarks (pt. 3) --- sys/kern/sleepq.c | 4 +++- sys/kern/syscalls.c | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/kern/sleepq.c b/sys/kern/sleepq.c index f87f5fa7eb..544cedd94b 100644 --- a/sys/kern/sleepq.c +++ b/sys/kern/sleepq.c @@ -325,7 +325,9 @@ int sleepq_wait_timed(void *wchan, const void *waitpt, mtx_t *mtx, } td->td_flags |= TDF_SLPINTR; - td->td_flags |= (timeout > 0) ? TDF_SLPTIMED : 0; + if (timeout > 0) + td->td_flags |= TDF_SLPTIMED; + sq_enter(td, sc, wchan, waitpt); /* After wakeup, only one of the following flags may be set: diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 53905f5222..0798b0364d 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1,3 +1,4 @@ +#define KL_LOG KL_SYSCALL #include #include #include @@ -25,7 +26,6 @@ #include #include -#include "sys/sigtypes.h" #include "sysent.h" /* Empty syscall handler, for unimplemented and deprecated syscall numbers. */ @@ -1347,12 +1347,10 @@ static int sys_sigtimedwait(proc_t *p, sigtimedwait_args_t *args, return error; } - error = copyin_s(u_set, set); - if (error) + if ((error = copyin_s(u_set, set))) return error; - error = do_sigtimedwait(p, set, &ksi, u_timeout ? &timeout : NULL); - if (error) + if ((error = do_sigtimedwait(p, set, &ksi, u_timeout ? &timeout : NULL))) return error; if (u_info) From d1df936217ed11d816f43bd9e18734ac474c7d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Bac=C5=82awski?= Date: Fri, 28 Jul 2023 21:11:18 +0200 Subject: [PATCH 35/35] Fix tests. --- bin/utest/Makefile | 2 ++ bin/utest/libwrap/xsigaction.c | 10 ++++++ bin/utest/libwrap/xsigprocmask.c | 10 ++++++ bin/utest/signal.c | 54 ++++++++++++++++---------------- bin/utest/utest.h | 6 ++++ 5 files changed, 55 insertions(+), 27 deletions(-) create mode 100644 bin/utest/libwrap/xsigaction.c create mode 100644 bin/utest/libwrap/xsigprocmask.c diff --git a/bin/utest/Makefile b/bin/utest/Makefile index 5e89aa20d7..00c77c4eaf 100644 --- a/bin/utest/Makefile +++ b/bin/utest/Makefile @@ -60,6 +60,8 @@ LIBWRAP = \ xsetresgid.c \ xsetresuid.c \ xsignal.c \ + xsigaction.c \ + xsigprocmask.c \ xstat.c \ xsymlink.c \ xunlink.c \ diff --git a/bin/utest/libwrap/xsigaction.c b/bin/utest/libwrap/xsigaction.c new file mode 100644 index 0000000000..f6730c91f9 --- /dev/null +++ b/bin/utest/libwrap/xsigaction.c @@ -0,0 +1,10 @@ +#include "utest.h" +#include + +void xsigaction(int sig, const struct sigaction *restrict act, + struct sigaction *restrict oact) { + int result = sigaction(sig, act, oact); + + if (result < 0) + die("sigaction: %s", strerror(errno)); +} diff --git a/bin/utest/libwrap/xsigprocmask.c b/bin/utest/libwrap/xsigprocmask.c new file mode 100644 index 0000000000..d471ab67e2 --- /dev/null +++ b/bin/utest/libwrap/xsigprocmask.c @@ -0,0 +1,10 @@ +#include "utest.h" +#include + +void xsigprocmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset) { + int result = sigprocmask(how, set, oset); + + if (result < 0) + die("sigprocmask: %s", strerror(errno)); +} diff --git a/bin/utest/signal.c b/bin/utest/signal.c index 1a9b905df6..9b88b84f34 100644 --- a/bin/utest/signal.c +++ b/bin/utest/signal.c @@ -226,8 +226,8 @@ TEST_ADD(signal_mask_nonmaskable, 0) { sigaddset(&set, SIGKILL); sigaddset(&set, SIGUSR1); /* The call should succeed, but SIGKILL and SIGSTOP shouldn't be blocked. */ - assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); - assert(sigprocmask(SIG_BLOCK, NULL, &set) == 0); + xsigprocmask(SIG_BLOCK, &set, &old); + xsigprocmask(SIG_BLOCK, NULL, &set); sigaddset(&old, SIGUSR1); assert(sigsetequal(&set, &old)); return 0; @@ -242,7 +242,7 @@ TEST_ADD(signal_sigsuspend, 0) { sigemptyset(&set); sigaddset(&set, SIGCONT); sigaddset(&set, SIGUSR1); - assert(sigprocmask(SIG_BLOCK, &set, &old) == 0); + xsigprocmask(SIG_BLOCK, &set, &old); sigaddset(&old, SIGCONT); pid_t cpid = xfork(); if (cpid == 0) { @@ -256,19 +256,19 @@ TEST_ADD(signal_sigsuspend, 0) { /* Go to sleep with SIGCONT blocked and SIGUSR1 unblocked. */ debug("Calling sigsuspend()..."); sigset_t current; - sigprocmask(SIG_BLOCK, NULL, ¤t); + xsigprocmask(SIG_BLOCK, NULL, ¤t); assert(sigismember(¤t, SIGUSR1)); assert(!sigismember(&old, SIGUSR1)); sigsuspend(&old); /* Check if mask is set back after waking up */ - sigprocmask(SIG_BLOCK, NULL, &set); + xsigprocmask(SIG_BLOCK, NULL, &set); assert(sigsetequal(&set, ¤t)); /* SIGUSR1 should have woken us up, but SIGCONT should still be pending. */ assert(sigusr1_handled); assert(!sigcont_handled); sigemptyset(&set); sigaddset(&set, SIGCONT); - assert(sigprocmask(SIG_UNBLOCK, &set, NULL) == 0); + xsigprocmask(SIG_UNBLOCK, &set, NULL); assert(sigcont_handled); wait_child_finished(cpid); @@ -278,19 +278,19 @@ TEST_ADD(signal_sigsuspend, 0) { /* ======= signal_sigtimedwait ======= */ static int sigtimedwait_child(__unused void *arg) { pid_t ppid = getppid(); - syscall_ok(kill(ppid, SIGUSR1)); + xkill(ppid, SIGUSR1); return 0; } -TEST_ADD(signal_sigtimedwait) { - syscall_ok(signal(SIGCONT, sigcont_handler)); +TEST_ADD(signal_sigtimedwait, 0) { + xsignal(SIGCONT, sigcont_handler); sigset_t set, current, waitset; sigemptyset(&set); sigaddset(&set, SIGUSR1); sigaddset(&set, SIGCONT); - syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); + xsigprocmask(SIG_SETMASK, &set, NULL); - utest_spawn(sigtimedwait_child, NULL); + spawn(sigtimedwait_child, NULL); siginfo_t info; sigemptyset(&waitset); @@ -298,27 +298,27 @@ TEST_ADD(signal_sigtimedwait) { assert(sigtimedwait(&waitset, &info, NULL) == SIGUSR1); assert(info.si_signo == SIGUSR1); - syscall_ok(sigprocmask(SIG_BLOCK, NULL, ¤t)); + xsigprocmask(SIG_BLOCK, NULL, ¤t); assert(sigsetequal(&set, ¤t)); - utest_child_exited(0); + wait_child_finished(0); return 0; } /* ======= signal_sigtimedwait_timeout ======= */ static int sigtimedwait_timeout_child(__unused void *arg) { ppid = getppid(); - kill(ppid, SIGUSR1); - kill(ppid, SIGCONT); + xkill(ppid, SIGUSR1); + xkill(ppid, SIGCONT); return 0; } -TEST_ADD(signal_sigtimedwait_timeout) { - syscall_ok(signal(SIGCONT, sigcont_handler)); +TEST_ADD(signal_sigtimedwait_timeout, 0) { + xsignal(SIGCONT, sigcont_handler); sigset_t set, waitset; sigemptyset(&set); sigaddset(&set, SIGUSR1); - syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); + xsigprocmask(SIG_SETMASK, &set, NULL); siginfo_t info; sigemptyset(&waitset); @@ -339,7 +339,7 @@ TEST_ADD(signal_sigtimedwait_timeout) { /* Should timeout. */ syscall_fail(sigtimedwait(&waitset, &info, &timeout), EAGAIN); - utest_spawn(sigtimedwait_timeout_child, NULL); + spawn(sigtimedwait_timeout_child, NULL); /* If we handled sigcont, then SIGUSR1 must be pending. */ while (!sigcont_handled) @@ -350,7 +350,7 @@ TEST_ADD(signal_sigtimedwait_timeout) { assert(sigtimedwait(&waitset, &info, &timeout) == SIGUSR1); assert(info.si_signo == SIGUSR1); - utest_child_exited(0); + wait_child_finished(0); return 0; } @@ -358,28 +358,28 @@ TEST_ADD(signal_sigtimedwait_timeout) { int sigtimedwait_intr_child(void *arg) { pid_t ppid = getppid(); while (!sigcont_handled) { - kill(ppid, SIGCONT); + xkill(ppid, SIGCONT); } return 0; } -TEST_ADD(signal_sigtimedwait_intr) { - syscall_ok(signal(SIGCONT, sigcont_handler)); +TEST_ADD(signal_sigtimedwait_intr, 0) { + xsignal(SIGCONT, sigcont_handler); sigset_t set, waitset; sigemptyset(&set); sigaddset(&set, SIGUSR1); - syscall_ok(sigprocmask(SIG_SETMASK, &set, NULL)); + xsigprocmask(SIG_SETMASK, &set, NULL); siginfo_t info; sigemptyset(&waitset); sigaddset(&waitset, SIGUSR1); - pid_t cpid = utest_spawn(sigtimedwait_intr_child, NULL); + pid_t cpid = spawn(sigtimedwait_intr_child, NULL); syscall_fail(sigtimedwait(&waitset, &info, NULL), EINTR); - syscall_ok(kill(cpid, SIGCONT)); - utest_child_exited(0); + xkill(cpid, SIGCONT); + wait_child_finished(0); return 0; } diff --git a/bin/utest/utest.h b/bin/utest/utest.h index f5f5fd4da2..3e1aa2681b 100644 --- a/bin/utest/utest.h +++ b/bin/utest/utest.h @@ -95,9 +95,11 @@ void wait_child_continued(pid_t pid); #include #include +#include typedef void (*sig_t)(int); struct stat; +struct sigaction; struct timezone; struct timeval; @@ -124,6 +126,10 @@ int xopen(const char *path, int flags, ...); void xpipe(int pipefd[2]); void xrmdir(const char *pathname); sig_t xsignal(int sig, sig_t func); +void xsigaction(int sig, const struct sigaction *restrict act, + struct sigaction *restrict oact); +void xsigprocmask(int how, const sigset_t *restrict set, + sigset_t *restrict oset); void xsetgroups(int size, gid_t *list); void xsetresuid(uid_t ruid, uid_t euid, uid_t suid); void xsetresgid(gid_t rgid, gid_t egid, gid_t sgid);