Browse Source

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.
pull/2/head
Lephenixnoir 1 year ago
parent
commit
cd7fe7a329
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
  1. 4
      CMakeLists.txt
  2. 11
      STATUS
  3. 35
      include/signal.h
  4. 3
      include/stdlib.h
  5. 20
      include/target/gint/bits/signum.h
  6. 2
      include/target/vhex-generic/bits/signum.h
  7. 35
      src/libc/signal/raise.c
  8. 19
      src/libc/signal/signal.c
  9. 13
      src/libc/signal/signal_p.h
  10. 5
      src/libc/stdlib/abort.c

4
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

11
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 <assert.h>
! 7.2.1 assert: LDEPS(fprintf,stderr,abort)
! 7.2.1 assert: LDEPS(fprintf,stderr)
7.3 <complex.h> => OpenLibm
@ -72,9 +72,10 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
7.13.2 longjmp: DONE
7.14 <signal.h>
! 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 <stdarg.h> => 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)

35
include/signal.h

@ -3,38 +3,49 @@
#include <stddef.h>
#include <stdint.h>
#include <stdatomic.h>
/* C99 API. */
typedef volatile atomic_int sig_atomic_t;
/* Type of a signal handler.*/
typedef void (*__sighandler_t)(int);
#include <bits/signum.h>
/* 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 <bits/sigaction.h>
#include <sys/types.h>
/* 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__*/

3
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);

20
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__*/

2
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

35
src/libc/signal/raise.c

@ -0,0 +1,35 @@
#include <signal.h>
#include <bits/signum.h>
#include <stdlib.h>
#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*/

19
src/libc/signal/signal.c

@ -0,0 +1,19 @@
#include <signal.h>
#include <bits/signum.h>
#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*/

13
src/libc/signal/signal_p.h

@ -0,0 +1,13 @@
#ifndef __SIGNAL_P_H__
# define __SIGNAL_P_H__
#ifdef __SUPPORT_VHEX_KERNEL
#include <bits/signum.h>
/* Handlers for all signals. */
extern __sighandler_t __signal_handlers[_NSIG];
#endif /*! __SUPPORT_VHEX_KERNEL*/
#endif /*__SIGNAL_P_H__*/

5
src/libc/stdlib/abort.c

@ -1,10 +1,11 @@
#include <stdlib.h>
#include <bits/stdlib.h>
#include <signal.h>
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);
}

Loading…
Cancel
Save