From cd7fe7a3292232e0fceb640fae76d0b6d89c1ce5 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 29 May 2021 18:26:33 +0200 Subject: [PATCH] signal: simple implementation (DONE) This version of signal (which does not rely on a notion of userland processes and is thus excluded from Vhex) follows C99 semantics but does not generate any signals by default. Basically, the signal function sets up function pointers and the signal function calls them. Termination signals call exit() while other signals call _Exit(), which is a quicker program termination similar to abort(). C99 allows programs to long jump out of signal handlers (!) which is unbelievably scary because it would bypass stack switching code in Vhex as well as normal interrupt handler termination in gint. --- CMakeLists.txt | 4 +++ STATUS | 11 +++---- include/signal.h | 35 +++++++++++++++-------- include/stdlib.h | 3 ++ include/target/gint/bits/signum.h | 20 +++++++++++++ include/target/vhex-generic/bits/signum.h | 2 +- src/libc/signal/raise.c | 35 +++++++++++++++++++++++ src/libc/signal/signal.c | 19 ++++++++++++ src/libc/signal/signal_p.h | 13 +++++++++ src/libc/stdlib/abort.c | 5 ++-- 10 files changed, 127 insertions(+), 20 deletions(-) create mode 100644 include/target/gint/bits/signum.h create mode 100644 src/libc/signal/raise.c create mode 100644 src/libc/signal/signal.c create mode 100644 src/libc/signal/signal_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index df5a90a..fb19d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,9 @@ set(SOURCES # locale src/libc/locale/setlocale.c src/libc/locale/localeconv.c + # signal + src/libc/signal/signal.c + src/libc/signal/raise.c # stdio src/libc/stdio/vsnprintf.c src/libc/stdio/sprintf.c @@ -121,6 +124,7 @@ set(SOURCES src/libc/stdio/vdprintf.c src/libc/stdio/printf.c # stdlib + src/libc/stdlib/abort.c src/libc/stdlib/abs.c src/libc/stdlib/atof.c src/libc/stdlib/atoi.c diff --git a/STATUS b/STATUS index 4a7db56..3de77b1 100644 --- a/STATUS +++ b/STATUS @@ -34,7 +34,7 @@ TEST: Function/symbol/macro needs to be tested DONE: Function/symbol/macro is defined, builds, links, and is tested 7.2 -! 7.2.1 assert: LDEPS(fprintf,stderr,abort) +! 7.2.1 assert: LDEPS(fprintf,stderr) 7.3 => OpenLibm @@ -72,9 +72,10 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested 7.13.2 longjmp: DONE 7.14 -! 7.14.1 Macros and stuff: TODO -! 7.14.1.1 signal: TODO -! 7.14.1.2 raise: TODO + 7.14 sig_atomic_t SIG_DFL SIG_ERR SIG_IGN: DONE + 7.14 SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM: DONE + 7.14.1.1 signal: DONE + 7.14.1.2 raise: DONE 7.15 => GCC @@ -102,7 +103,7 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested 7.20.1.4 strtol, strtoul, strtoll, strtoull: DONE ! 7.20.2 Pseudo-random sequence generation functions: TODO ! 7.20.3 Memory management functions: TODO (check existing code first) -! 7.20.4.1 abort: BDEPS(raise) + 7.20.4.1 abort: DONE ! 7.20.4.2 atexit: TODO 7.20.4.3 exit: DONE (missing stream flushing/closing/etc) 7.20.4.4 _Exit: DONE (gint only) diff --git a/include/signal.h b/include/signal.h index be133bb..17f7405 100644 --- a/include/signal.h +++ b/include/signal.h @@ -3,38 +3,49 @@ #include #include +#include + +/* C99 API. */ + +typedef volatile atomic_int sig_atomic_t; + +/* Type of a signal handler.*/ +typedef void (*__sighandler_t)(int); #include +/* Set the handler for __signum. */ +extern __sighandler_t signal(int __signum, __sighandler_t __handler); + +/* Raise signal __signum. */ +extern int raise(int __signum); + +/* POSIX API (Vhex only). */ + +#ifdef _POSIX_C_SOURCE + /* Type of signal set */ typedef uint32_t sigset_t; typedef uint32_t kernel_sigset_t; -/* Type of a signal handler.*/ -typedef void (*__sighandler_t)(int); -typedef __sighandler_t sighandler_t; - /* ** Get the system-specific definitions of `struct sigaction' and the `SA_*' ** and `SIG_*'. constants. */ #include +#include /* Get and/or change the set of blocked signals. */ -extern int sigprocmask (int how, const sigset_t *restrict set, - sigset_t *restrict oldset); +extern int sigprocmask (int __how, const sigset_t *restrict __set, + sigset_t *restrict __oldset); /* ** Send signal SIG to process number PID. If PID is zero, send SIG to all ** processes in the current process's process group. If PID is < -1, send SIG to ** all processes in process group - PID. */ -extern int kill(pid_t pid, int sig); +extern int kill(pid_t __pid, int __sig); -/* -** Set the handler for the signal SIG to HANDLER, returning the old handler, or -** SIG_ERR on error. By default `signal' has the BSD semantic. -*/ -extern void (*signal(int signum, void (*handler)(int)))(int); +#endif /*_POSIX_C_SOURCE*/ #endif /*__SIGNAL_H__*/ diff --git a/include/stdlib.h b/include/stdlib.h index d13e30b..5f68ab0 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -30,6 +30,9 @@ extern void free(void *__ptr); /* Communication with the environment. */ +/* Abort execution; raises SIGABRT and leaves quickly with _Exit(). */ +void abort(void); + /* Exit; calls handlers, flushes and closes streams and temporary files. */ void exit(int __status); diff --git a/include/target/gint/bits/signum.h b/include/target/gint/bits/signum.h new file mode 100644 index 0000000..a340352 --- /dev/null +++ b/include/target/gint/bits/signum.h @@ -0,0 +1,20 @@ +#ifndef __BITS_SIGNUM_H__ +# define __BITS_SIGNUM_H__ + +// Define the number of signals +#define _NSIG 16 + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +/* ISO C99 signals. */ +#define SIGINT 2 /* Interactive attention signal. */ +#define SIGILL 4 /* Illegal instruction. */ +#define SIGABRT 6 /* Abnormal termination. */ +#define SIGFPE 8 /* Erroneous arithmetic operation. */ +#define SIGSEGV 11 /* Invalid access to storage. */ +#define SIGTERM 15 /* Termination request. */ + +#endif /*__BITS_SIGNUM_H__*/ diff --git a/include/target/vhex-generic/bits/signum.h b/include/target/vhex-generic/bits/signum.h index 36cdb1e..d3e9fca 100644 --- a/include/target/vhex-generic/bits/signum.h +++ b/include/target/vhex-generic/bits/signum.h @@ -2,7 +2,7 @@ # define __BITS_SIGNUM_H__ // Define the number of signals -#define NSIG 32 +#define _NSIG 32 // Vhex kernel internal define used to indicate // if the signal is implemented or not diff --git a/src/libc/signal/raise.c b/src/libc/signal/raise.c new file mode 100644 index 0000000..573c654 --- /dev/null +++ b/src/libc/signal/raise.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "signal_p.h" + +#ifndef __SUPPORT_VHEX_KERNEL + +int raise(int sig) +{ + if(sig < 0 || sig >= _NSIG) + return 1; + + /* TODO: libc/signal: support signal masks? */ + __sighandler_t handler = signal(sig, SIG_DFL); + + if(handler == SIG_DFL) { + /* Signals that terminate */ + if(sig == SIGINT || sig == SIGTERM) { + exit(128 + sig); + } + /* Signals that abort */ + if(sig == SIGILL || sig == SIGABRT || sig == SIGFPE || + sig == SIGSEGV) { + _Exit(128 + sig); + } + } + else if(handler != SIG_IGN) { + (*handler)(sig); + } + + signal(sig, handler); + return 0; +} + +#endif /*! __SUPPORT_VHEX_KERNEL*/ diff --git a/src/libc/signal/signal.c b/src/libc/signal/signal.c new file mode 100644 index 0000000..bfb10a2 --- /dev/null +++ b/src/libc/signal/signal.c @@ -0,0 +1,19 @@ +#include +#include +#include "signal_p.h" + +#ifndef __SUPPORT_VHEX_KERNEL + +__sighandler_t __signal_handlers[_NSIG] = { 0 }; + +__sighandler_t signal(int signum, __sighandler_t handler) +{ + if(signum < 0 || signum >= _NSIG) + return SIG_ERR; + + __sighandler_t prev = __signal_handlers[signum]; + __signal_handlers[signum] = handler; + return prev; +} + +#endif /*! __SUPPORT_VHEX_KERNEL*/ diff --git a/src/libc/signal/signal_p.h b/src/libc/signal/signal_p.h new file mode 100644 index 0000000..b2b024c --- /dev/null +++ b/src/libc/signal/signal_p.h @@ -0,0 +1,13 @@ +#ifndef __SIGNAL_P_H__ +# define __SIGNAL_P_H__ + +#ifdef __SUPPORT_VHEX_KERNEL + +#include + +/* Handlers for all signals. */ +extern __sighandler_t __signal_handlers[_NSIG]; + +#endif /*! __SUPPORT_VHEX_KERNEL*/ + +#endif /*__SIGNAL_P_H__*/ diff --git a/src/libc/stdlib/abort.c b/src/libc/stdlib/abort.c index 2191df9..39bc40b 100644 --- a/src/libc/stdlib/abort.c +++ b/src/libc/stdlib/abort.c @@ -1,10 +1,11 @@ #include -#include +#include -void abort(int rc) +void abort(void) { /* TODO: Close BFile handles (essential) */ raise(SIGABRT); + /* If the signal handler ever returns, leave on our own */ _Exit(EXIT_FAILURE); }