From 702bdf4497a72b422c591f69c45aa0be0ee23731 Mon Sep 17 00:00:00 2001 From: solar Date: Fri, 10 Dec 2010 06:21:48 +0000 Subject: [PATCH] Completed , and moved into platform. --- includes/signal.h | 39 -------- .../example/functions}/signal/raise.c | 25 ++++-- .../example/functions}/signal/signal.c | 25 +++--- platform/example/includes/signal.h | 90 +++++++++++++++++++ platform/example/internals/_PDCLIB_config.h | 36 -------- .../example_64/internals/_PDCLIB_config.h | 36 -------- .../example_cygwin/functions/signal/raise.c | 71 +++++++++++++++ .../example_cygwin/functions/signal/signal.c | 71 +++++++++++++++ platform/example_cygwin/includes/signal.h | 90 +++++++++++++++++++ .../example_cygwin/internals/_PDCLIB_config.h | 36 -------- 10 files changed, 351 insertions(+), 168 deletions(-) delete mode 100644 includes/signal.h rename {functions => platform/example/functions}/signal/raise.c (65%) rename {functions => platform/example/functions}/signal/signal.c (72%) create mode 100644 platform/example/includes/signal.h create mode 100644 platform/example_cygwin/functions/signal/raise.c create mode 100644 platform/example_cygwin/functions/signal/signal.c create mode 100644 platform/example_cygwin/includes/signal.h diff --git a/includes/signal.h b/includes/signal.h deleted file mode 100644 index 7123b4a..0000000 --- a/includes/signal.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $Id$ */ - -/* Signal handling - - This file is part of the Public Domain C Library (PDCLib). - Permission is granted to use, modify, and / or redistribute at will. -*/ - -#ifndef _PDCLIB_SIGNAL_H -#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H - -#ifndef _PDCLIB_CONFIG_H -#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H -#include <_PDCLIB_config.h> -#endif - -typedef _PDCLIB_sig_atomic sig_atomic_t; - -#define SIG_DFL _PDCLIB_SIG_DFL -#define SIG_ERR _PDCLIB_SIG_ERR -#define SIG_IGN _PDCLIB_SIG_IGN - -#define SIGABRT _PDCLIB_SIGABRT -#define SIGFPE _PDCLIB_SIGFPE -#define SIGILL _PDCLIB_SIGILL -#define SIGINT _PDCLIB_SIGINT -#define SIGSEGV _PDCLIB_SIGSEGV -#define SIGTERM _PDCLIB_SIGTERM - -/* Returns the value of func for the most recent successful call to signal() - for the signal sig. Returns SIG_ERR and sets errno to a positive value - otherwise. -*/ -void (*signal( int sig, void (*func)( int ) ) )( int ); - -/* Returns zero if successful, nonzero otherwise. */ -int raise( int sig ); - -#endif diff --git a/functions/signal/raise.c b/platform/example/functions/signal/raise.c similarity index 65% rename from functions/signal/raise.c rename to platform/example/functions/signal/raise.c index 29afe15..b16249c 100644 --- a/functions/signal/raise.c +++ b/platform/example/functions/signal/raise.c @@ -10,6 +10,8 @@ #ifndef REGTEST +#include + extern void (*_PDCLIB_sigabrt)( int ); extern void (*_PDCLIB_sigfpe)( int ); extern void (*_PDCLIB_sigill)( int ); @@ -19,31 +21,40 @@ extern void (*_PDCLIB_sigterm)( int ); int raise( int sig ) { + void (*sighandler)( int ); switch ( sig ) { case SIGABRT: - _PDCLIB_sigabrt( sig ); + sighandler = _PDCLIB_sigabrt; break; case SIGFPE: - _PDCLIB_sigfpe( sig ); + sighandler = _PDCLIB_sigfpe; break; case SIGILL: - _PDCLIB_sigill( sig ); + sighandler = _PDCLIB_sigill; break; case SIGINT: - _PDCLIB_sigint( sig ); + sighandler = _PDCLIB_sigint; break; case SIGSEGV: - _PDCLIB_sigsegv( sig ); + sighandler = _PDCLIB_sigsegv; break; case SIGTERM: - _PDCLIB_sigterm( sig ); + sighandler = _PDCLIB_sigterm; break; default: /* TODO: Implement. */ break; } - /* TODO: Implement. */ + if ( sighandler == SIG_DFL ) + { + _Exit( EXIT_FAILURE ); + } + else if ( sighandler != SIG_IGN ) + { + sighandler = signal( sig, SIG_DFL ); + sighandler( sig ); + } return 0; } diff --git a/functions/signal/signal.c b/platform/example/functions/signal/signal.c similarity index 72% rename from functions/signal/signal.c rename to platform/example/functions/signal/signal.c index fb1ff0b..33722ac 100644 --- a/functions/signal/signal.c +++ b/platform/example/functions/signal/signal.c @@ -12,18 +12,12 @@ #include -static void default_handler( int sig ) -{ - /* TODO: Implement error message */ - exit( EXIT_FAILURE ); -} - -void (*_PDCLIB_sigabrt)( int ) = default_handler; -void (*_PDCLIB_sigfpe)( int ) = default_handler; -void (*_PDCLIB_sigill)( int ) = default_handler; -void (*_PDCLIB_sigint)( int ) = default_handler; -void (*_PDCLIB_sigsegv)( int ) = default_handler; -void (*_PDCLIB_sigterm)( int ) = default_handler; +void (*_PDCLIB_sigabrt)( int ) = SIG_DFL; +void (*_PDCLIB_sigfpe)( int ) = SIG_DFL; +void (*_PDCLIB_sigill)( int ) = SIG_DFL; +void (*_PDCLIB_sigint)( int ) = SIG_DFL; +void (*_PDCLIB_sigsegv)( int ) = SIG_DFL; +void (*_PDCLIB_sigterm)( int ) = SIG_DFL; void (*signal( int sig, void (*func)( int ) ) )( int ) { @@ -55,8 +49,11 @@ void (*signal( int sig, void (*func)( int ) ) )( int ) _PDCLIB_sigterm = func; break; default: - /* TODO: Implement. */ - break; + /* The standard calls for an unspecified "positive value". You + will probably want to define a specific value for this. + */ + _PDCLIB_errno = 1; + return SIG_ERR; } return oldhandler; } diff --git a/platform/example/includes/signal.h b/platform/example/includes/signal.h new file mode 100644 index 0000000..e1b10f8 --- /dev/null +++ b/platform/example/includes/signal.h @@ -0,0 +1,90 @@ +/* $Id$ */ + +/* Signal handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_SIGNAL_H +#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H + +#ifndef _PDCLIB_CONFIG_H +#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H +#include <_PDCLIB_config.h> +#endif + +/* Signals ------------------------------------------------------------------ */ + +/* A word on signals, to the people using PDCLib in their OS projects. + + The definitions of the C standard leave about everything that *could* be + useful to be "implementation defined". Without additional, non-standard + arrangements, it is not possible to turn them into a useful tool. + + This example implementation chose to "not generate any of these signals, + except as a result of explicit calls to the raise function", which is + allowed by the standard but of course does nothing for the usefulness of + . + + A useful signal handling would: + 1) make signal() a system call that registers the signal handler with the OS + 2) make raise() a system call triggering an OS signal to the running process + 3) make provisions that further signals of the same type are blocked until + the signal handler returns (optional for SIGILL) +*/ + +/* These are the values used by Linux. */ + +/* Abnormal termination / abort() */ +#define SIGABRT 6 +/* Arithmetic exception / division by zero / overflow */ +#define SIGFPE 8 +/* Illegal instruction */ +#define SIGILL 4 +/* Interactive attention signal */ +#define SIGINT 2 +/* Invalid memory access */ +#define SIGSEGV 11 +/* Termination request */ +#define SIGTERM 15 + +/* The following should be defined to pointer values that could NEVER point to + a valid signal handler function. (They are used as special arguments to + signal().) Again, these are the values used by Linux. +*/ +#define SIG_DFL (void (*)( int ))0 +#define SIG_ERR (void (*)( int ))-1 +#define SIG_IGN (void (*)( int ))1 + +typedef _PDCLIB_sig_atomic sig_atomic_t; + +/* Installs a signal handler "func" for the given signal. + A signal handler is a function that takes an integer as argument (the signal + number) and returns void. + + Note that a signal handler can do very little else than: + 1) assign a value to a static object of type "volatile sig_atomic_t", + 2) call signal() with the value of sig equal to the signal received, + 3) call _Exit(), + 4) call abort(). + Virtually everything else is undefind. + + The signal() function returns the previous installed signal handler, which + at program start may be SIG_DFL or SIG_ILL. (This implementation uses + SIG_DFL for all handlers.) If the request cannot be honored, SIG_ERR is + returned and errno is set to an unspecified positive value. +*/ +void (*signal( int sig, void (*func)( int ) ) )( int ); + +/* Raises the given signal (executing the registered signal handler with the + given signal number as parameter). + This implementation does not prevent further signals of the same time from + occuring, but executes signal( sig, SIG_DFL ) before entering the signal + handler (i.e., a second signal before the signal handler re-registers itself + or SIG_IGN will end the program). + Returns zero if successful, nonzero otherwise. */ +int raise( int sig ); + +#endif + diff --git a/platform/example/internals/_PDCLIB_config.h b/platform/example/internals/_PDCLIB_config.h index 0f0c21c..f1d1475 100644 --- a/platform/example/internals/_PDCLIB_config.h +++ b/platform/example/internals/_PDCLIB_config.h @@ -285,39 +285,3 @@ typedef int _PDCLIB_fd_t; this capability dependent on implementation-defined behaviour (not good). */ #define _PDCLIB_UNGETCBUFSIZE 1 - -/* Signals ------------------------------------------------------------------ */ - -/* A word on signals, to the people using PDCLib in their OS projects. - - The way they are defined by the C standard severely limits their usefulness, - to the point where a library implementation need not interface with the OS' - signals at all (which is what the PDCLib example implementation does). - (Other issues include, for example, that signal handlers are not re-entrant.) - - Thus, it is strongly discouraged to try bolting on a signal handling infra- - structure onto . Since C's signal handling is so limited to begin - with, and code using it is pretty much non-portable anyway, it would be - smarter to keep in the barely functional state it is in, and - instead create a better, OS-specific API. - - That being said, the below signals require to be defined to a positive int - value. I took what my Linux box defined them to; if you have to change them, - and what value to change them *to*, depends heavily on your environment and - what you are expecting to accomplish (see above). -*/ -#define _PDCLIB_SIGABRT 6 -#define _PDCLIB_SIGFPE 8 -#define _PDCLIB_SIGILL 4 -#define _PDCLIB_SIGINT 2 -#define _PDCLIB_SIGSEGV 11 -#define _PDCLIB_SIGTERM 15 - -/* The following should be defined to pointer values that could NEVER point to - a valid function. (They are used as special arguments to signal().) Again, I - took the values of my Linux box, which should be as good as any other value. -*/ -#define _PDCLIB_SIG_DFL (void (*)( int ))0 -#define _PDCLIB_SIG_ERR (void (*)( int ))-1 -#define _PDCLIB_SIG_IGN (void (*)( int ))1 - diff --git a/platform/example_64/internals/_PDCLIB_config.h b/platform/example_64/internals/_PDCLIB_config.h index ba3de27..c50281a 100644 --- a/platform/example_64/internals/_PDCLIB_config.h +++ b/platform/example_64/internals/_PDCLIB_config.h @@ -278,39 +278,3 @@ typedef int _PDCLIB_fd_t; this capability dependent on implementation-defined behaviour (not good). */ #define _PDCLIB_UNGETCBUFSIZE 1 - -/* Signals ------------------------------------------------------------------ */ - -/* A word on signals, to the people using PDCLib in their OS projects. - - The way they are defined by the C standard severely limits their usefulness, - to the point where a library implementation need not interface with the OS' - signals at all (which is what the PDCLib example implementation does). - (Other issues include, for example, that signal handlers are not re-entrant.) - - Thus, it is strongly discouraged to try bolting on a signal handling infra- - structure onto . Since C's signal handling is so limited to begin - with, and code using it is pretty much non-portable anyway, it would be - smarter to keep in the barely functional state it is in, and - instead create a better, OS-specific API. - - That being said, the below signals require to be defined to a positive int - value. I took what my Linux box defined them to; if you have to change them, - and what value to change them *to*, depends heavily on your environment and - what you are expecting to accomplish (see above). -*/ -#define _PDCLIB_SIGABRT 6 -#define _PDCLIB_SIGFPE 8 -#define _PDCLIB_SIGILL 4 -#define _PDCLIB_SIGINT 2 -#define _PDCLIB_SIGSEGV 11 -#define _PDCLIB_SIGTERM 15 - -/* The following should be defined to pointer values that could NEVER point to - a valid function. (They are used as special arguments to signal().) Again, I - took the values of my Linux box, which should be as good as any other value. -*/ -#define _PDCLIB_SIG_DFL (void (*)( int ))0 -#define _PDCLIB_SIG_ERR (void (*)( int ))-1 -#define _PDCLIB_SIG_IGN (void (*)( int ))1 - diff --git a/platform/example_cygwin/functions/signal/raise.c b/platform/example_cygwin/functions/signal/raise.c new file mode 100644 index 0000000..b16249c --- /dev/null +++ b/platform/example_cygwin/functions/signal/raise.c @@ -0,0 +1,71 @@ +/* $Id$ */ + +/* raise( int ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include + +extern void (*_PDCLIB_sigabrt)( int ); +extern void (*_PDCLIB_sigfpe)( int ); +extern void (*_PDCLIB_sigill)( int ); +extern void (*_PDCLIB_sigint)( int ); +extern void (*_PDCLIB_sigsegv)( int ); +extern void (*_PDCLIB_sigterm)( int ); + +int raise( int sig ) +{ + void (*sighandler)( int ); + switch ( sig ) + { + case SIGABRT: + sighandler = _PDCLIB_sigabrt; + break; + case SIGFPE: + sighandler = _PDCLIB_sigfpe; + break; + case SIGILL: + sighandler = _PDCLIB_sigill; + break; + case SIGINT: + sighandler = _PDCLIB_sigint; + break; + case SIGSEGV: + sighandler = _PDCLIB_sigsegv; + break; + case SIGTERM: + sighandler = _PDCLIB_sigterm; + break; + default: + /* TODO: Implement. */ + break; + } + if ( sighandler == SIG_DFL ) + { + _Exit( EXIT_FAILURE ); + } + else if ( sighandler != SIG_IGN ) + { + sighandler = signal( sig, SIG_DFL ); + sighandler( sig ); + } + return 0; +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} +#endif diff --git a/platform/example_cygwin/functions/signal/signal.c b/platform/example_cygwin/functions/signal/signal.c new file mode 100644 index 0000000..33722ac --- /dev/null +++ b/platform/example_cygwin/functions/signal/signal.c @@ -0,0 +1,71 @@ +/* $Id$ */ + +/* signal( int sig, void (*func)( int ) ) + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#include + +#ifndef REGTEST + +#include + +void (*_PDCLIB_sigabrt)( int ) = SIG_DFL; +void (*_PDCLIB_sigfpe)( int ) = SIG_DFL; +void (*_PDCLIB_sigill)( int ) = SIG_DFL; +void (*_PDCLIB_sigint)( int ) = SIG_DFL; +void (*_PDCLIB_sigsegv)( int ) = SIG_DFL; +void (*_PDCLIB_sigterm)( int ) = SIG_DFL; + +void (*signal( int sig, void (*func)( int ) ) )( int ) +{ + void (*oldhandler)( int ); + switch ( sig ) + { + case SIGABRT: + oldhandler = _PDCLIB_sigabrt; + _PDCLIB_sigabrt = func; + break; + case SIGFPE: + oldhandler = _PDCLIB_sigfpe; + _PDCLIB_sigfpe = func; + break; + case SIGILL: + oldhandler = _PDCLIB_sigill; + _PDCLIB_sigill = func; + break; + case SIGINT: + oldhandler = _PDCLIB_sigint; + _PDCLIB_sigint = func; + break; + case SIGSEGV: + oldhandler = _PDCLIB_sigsegv; + _PDCLIB_sigsegv = func; + break; + case SIGTERM: + oldhandler = _PDCLIB_sigterm; + _PDCLIB_sigterm = func; + break; + default: + /* The standard calls for an unspecified "positive value". You + will probably want to define a specific value for this. + */ + _PDCLIB_errno = 1; + return SIG_ERR; + } + return oldhandler; +} + +#endif + +#ifdef TEST +#include <_PDCLIB_test.h> + +int main( void ) +{ + TESTCASE( NO_TESTDRIVER ); + return TEST_RESULTS; +} +#endif diff --git a/platform/example_cygwin/includes/signal.h b/platform/example_cygwin/includes/signal.h new file mode 100644 index 0000000..e1b10f8 --- /dev/null +++ b/platform/example_cygwin/includes/signal.h @@ -0,0 +1,90 @@ +/* $Id$ */ + +/* Signal handling + + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. +*/ + +#ifndef _PDCLIB_SIGNAL_H +#define _PDCLIB_SIGNAL_H _PDCLIB_SIGNAL_H + +#ifndef _PDCLIB_CONFIG_H +#define _PDCLIB_CONFIG_H _PDCLIB_CONFIG_H +#include <_PDCLIB_config.h> +#endif + +/* Signals ------------------------------------------------------------------ */ + +/* A word on signals, to the people using PDCLib in their OS projects. + + The definitions of the C standard leave about everything that *could* be + useful to be "implementation defined". Without additional, non-standard + arrangements, it is not possible to turn them into a useful tool. + + This example implementation chose to "not generate any of these signals, + except as a result of explicit calls to the raise function", which is + allowed by the standard but of course does nothing for the usefulness of + . + + A useful signal handling would: + 1) make signal() a system call that registers the signal handler with the OS + 2) make raise() a system call triggering an OS signal to the running process + 3) make provisions that further signals of the same type are blocked until + the signal handler returns (optional for SIGILL) +*/ + +/* These are the values used by Linux. */ + +/* Abnormal termination / abort() */ +#define SIGABRT 6 +/* Arithmetic exception / division by zero / overflow */ +#define SIGFPE 8 +/* Illegal instruction */ +#define SIGILL 4 +/* Interactive attention signal */ +#define SIGINT 2 +/* Invalid memory access */ +#define SIGSEGV 11 +/* Termination request */ +#define SIGTERM 15 + +/* The following should be defined to pointer values that could NEVER point to + a valid signal handler function. (They are used as special arguments to + signal().) Again, these are the values used by Linux. +*/ +#define SIG_DFL (void (*)( int ))0 +#define SIG_ERR (void (*)( int ))-1 +#define SIG_IGN (void (*)( int ))1 + +typedef _PDCLIB_sig_atomic sig_atomic_t; + +/* Installs a signal handler "func" for the given signal. + A signal handler is a function that takes an integer as argument (the signal + number) and returns void. + + Note that a signal handler can do very little else than: + 1) assign a value to a static object of type "volatile sig_atomic_t", + 2) call signal() with the value of sig equal to the signal received, + 3) call _Exit(), + 4) call abort(). + Virtually everything else is undefind. + + The signal() function returns the previous installed signal handler, which + at program start may be SIG_DFL or SIG_ILL. (This implementation uses + SIG_DFL for all handlers.) If the request cannot be honored, SIG_ERR is + returned and errno is set to an unspecified positive value. +*/ +void (*signal( int sig, void (*func)( int ) ) )( int ); + +/* Raises the given signal (executing the registered signal handler with the + given signal number as parameter). + This implementation does not prevent further signals of the same time from + occuring, but executes signal( sig, SIG_DFL ) before entering the signal + handler (i.e., a second signal before the signal handler re-registers itself + or SIG_IGN will end the program). + Returns zero if successful, nonzero otherwise. */ +int raise( int sig ); + +#endif + diff --git a/platform/example_cygwin/internals/_PDCLIB_config.h b/platform/example_cygwin/internals/_PDCLIB_config.h index 8512ad9..2fd09e9 100644 --- a/platform/example_cygwin/internals/_PDCLIB_config.h +++ b/platform/example_cygwin/internals/_PDCLIB_config.h @@ -287,39 +287,3 @@ typedef int _PDCLIB_fd_t; #define _PDCLIB_UNGETCBUFSIZE 1 typedef long wint_t; - -/* Signals ------------------------------------------------------------------ */ - -/* A word on signals, to the people using PDCLib in their OS projects. - - The way they are defined by the C standard severely limits their usefulness, - to the point where a library implementation need not interface with the OS' - signals at all (which is what the PDCLib example implementation does). - (Other issues include, for example, that signal handlers are not re-entrant.) - - Thus, it is strongly discouraged to try bolting on a signal handling infra- - structure onto . Since C's signal handling is so limited to begin - with, and code using it is pretty much non-portable anyway, it would be - smarter to keep in the barely functional state it is in, and - instead create a better, OS-specific API. - - That being said, the below signals require to be defined to a positive int - value. I took what my Linux box defined them to; if you have to change them, - and what value to change them *to*, depends heavily on your environment and - what you are expecting to accomplish (see above). -*/ -#define _PDCLIB_SIGABRT 6 -#define _PDCLIB_SIGFPE 8 -#define _PDCLIB_SIGILL 4 -#define _PDCLIB_SIGINT 2 -#define _PDCLIB_SIGSEGV 11 -#define _PDCLIB_SIGTERM 15 - -/* The following should be defined to pointer values that could NEVER point to - a valid function. (They are used as special arguments to signal().) Again, I - took the values of my Linux box, which should be as good as any other value. -*/ -#define _PDCLIB_SIG_DFL (void (*)( int ))0 -#define _PDCLIB_SIG_ERR (void (*)( int ))-1 -#define _PDCLIB_SIG_IGN (void (*)( int ))1 - -- 2.40.0