diff --git a/README.txt b/README.txt index 53aa2f880d4..941aa03685f 100644 --- a/README.txt +++ b/README.txt @@ -439,7 +439,7 @@ Refreshing Configurations be? Enter ? in response to the 'make oldconfig' prompt and it will show you the help text that goes with the option. - If you don't want to make any decisions are are willing to just accep the + If you don't want to make any decisions are are willing to just accept the recommended default value for each new configuration item, an even easier way is: diff --git a/include/signal.h b/include/signal.h index 146edfc0fc4..12585c91e31 100644 --- a/include/signal.h +++ b/include/signal.h @@ -181,17 +181,10 @@ * functions that deal with signal disposition. */ -#define SIG_ERR ((CODE void*)-1) -#define SIG_DFL ((CODE void*)0) -#define SIG_IGN ((CODE void*)0) - -#if 0 /* Not yet supported */ -# define SIG_HOLD ((CODE void*)0) -#endif - -/* System V name compatibility */ - -#define sigset(s,f) signal(s,f) +#define SIG_ERR ((CODE void *)-1) /* And error occurred */ +#define SIG_DFL ((CODE void *)0) /* Default is SIG_IGN for all signals */ +#define SIG_IGN ((CODE void *)0) /* Ignore the signal */ +#define SIG_HOLD ((CODE void *)1) /* Used only with sigset() */ /******************************************************************************** * Public Type Definitions @@ -289,29 +282,30 @@ extern "C" #endif int kill(pid_t, int); -int sigemptyset(FAR sigset_t *set); -int sigfillset(FAR sigset_t *set); -int sigaddset(FAR sigset_t *set, int signo); -int sigdelset(FAR sigset_t *set, int signo); -int sigismember(FAR const sigset_t *set, int signo); int sigaction(int sig, FAR const struct sigaction *act, FAR struct sigaction *oact); +int sigaddset(FAR sigset_t *set, int signo); +int sigdelset(FAR sigset_t *set, int signo); +int sigemptyset(FAR sigset_t *set); +int sigfillset(FAR sigset_t *set); +int sighold(int signo); +int sigismember(FAR const sigset_t *set, int signo); int sigignore(int signo); CODE void (*signal(int sig, CODE void (*func)(int signo)))(int signo); int sigprocmask(int how, FAR const sigset_t *set, FAR sigset_t *oset); int sigpause(int signo); -int sigrelse(int signo); int sigpending(FAR sigset_t *set); -int sighold(int signo); -int sigsuspend(FAR const sigset_t *sigmask); -int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *value); -int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *value, - FAR const struct timespec *timeout); #ifdef CONFIG_CAN_PASS_STRUCTS int sigqueue(int pid, int signo, union sigval value); #else int sigqueue(int pid, int signo, FAR void *sival_ptr); #endif +int sigrelse(int signo); +CODE void (*sigset(int sig, CODE void (*func)(int signo)))(int signo); +int sigtimedwait(FAR const sigset_t *set, FAR struct siginfo *value, + FAR const struct timespec *timeout); +int sigsuspend(FAR const sigset_t *sigmask); +int sigwaitinfo(FAR const sigset_t *set, FAR struct siginfo *value); #undef EXTERN #ifdef __cplusplus diff --git a/libc/signal/Make.defs b/libc/signal/Make.defs index aa3b473baf3..0c642ff8c75 100644 --- a/libc/signal/Make.defs +++ b/libc/signal/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # libc/signal/Make.defs # -# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. +# Copyright (C) 2011-2012, 2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -39,7 +39,7 @@ ifneq ($(CONFIG_DISABLE_SIGNALS),y) CSRCS += sig_emptyset.c sig_fillset.c sig_addset.c sig_delset.c CSRCS += sig_ismember.c sig_hold.c sig_relse.c sig_ignore.c sig_pause.c -CSRCS += signal.c +CSRCS += sig_set.c signal.c # Add the signal directory to the build diff --git a/libc/signal/sig_fillset.c b/libc/signal/sig_fillset.c index 92f55edf409..a064242c344 100644 --- a/libc/signal/sig_fillset.c +++ b/libc/signal/sig_fillset.c @@ -39,26 +39,6 @@ #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - /**************************************************************************** * Publics Functions ****************************************************************************/ diff --git a/libc/signal/sig_ismember.c b/libc/signal/sig_ismember.c index c16ecd3d15c..6240392011d 100644 --- a/libc/signal/sig_ismember.c +++ b/libc/signal/sig_ismember.c @@ -39,26 +39,6 @@ #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Type Declarations - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/libc/signal/sig_relse.c b/libc/signal/sig_relse.c index 62e86a895f2..aa9cd841233 100644 --- a/libc/signal/sig_relse.c +++ b/libc/signal/sig_relse.c @@ -47,8 +47,8 @@ * Name: sigrelse * * Description: - * The sigrelse() function will remove 'signo' to the calling process' signal - * mask. + * The sigrelse() function will remove 'signo' from the calling process' + * signal mask. * ****************************************************************************/ diff --git a/libc/signal/sig_set.c b/libc/signal/sig_set.c new file mode 100644 index 00000000000..b7fe7c603b2 --- /dev/null +++ b/libc/signal/sig_set.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * libc/signal/sig_set.c + * + * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sigset + * + * Description: + * The signal() function will modify signal dispositions. The 'signo' + * argument specifies the signal. The 'func' argument specifies the + * signal's disposition, which may be SIG_DFL, SIG_IGN, or the address + * of a signal handler. + * + * The System V sigset function is very similar to the (obsolete) POSIX + * signal() function except that it includes additional managment of the + * tasks' signal mask. This function is then simply a wrapper around + * signal() with this additional signal mask logic added. + * + * - The sigset set function also accepts the SIG_HOLD value for 'func': + * If 'func' is equal to SIG_HOLD, 'signo' will be added to the signal + * mask of the calling process and 'signo's disposition will remain + * unchanged. + * - If 'func' is not equal to SIG_HOLD, 'signo' will be removed from the + * signal mask of the calling process. + * + * Input Parameters: + * signo - Identifies the signal to operate on + * func - The new disposition of the signal + * + * Returned Value: + * Upon successful completion, sigset() shall return SIG_HOLD if the + * signal had been blocked and the signal's previous disposition if it had + * not been blocked. Otherwise, SIG_ERR shall be returned and errno set to + * indicate the error. + * + * Hmm.. this wording is not clear to me. I assume this to mean: + * + * if (func == SIG_HOLD) + * { + * Set mask + * if (mask successfuly set) + * { + * return SIG_HOLD + * } + * else + * { + * return SIG_ERR + * } + * else + * { + * Set disposition + * if (disposition successfuly set) + * { + * return old disposition + * } + * else + * { + * return SIG_ERR + * } + * } + * + * But you could also argue that the English means to return SIG_HOLD in + * any case is the signal is blocked. And, in that case would you set the + * disposition or not? Unclear. + * + ****************************************************************************/ + +CODE void (*sigset(int signo, CODE void (*func)(int signo)))(int signo) +{ + _sa_handler_t disposition; + sigset_t set; + int ret; + + DEBUGASSERT(GOOD_SIGNO(signo) && func != NULL); + + (void)sigemptyset(&set); + (void)sigaddset(&set, signo); + + /* Check if we are being asked to block the signal */ + + if (func == SIG_HOLD) + { + ret = sigprocmask(SIG_BLOCK, &set, NULL); + disposition = ret < 0 ? SIG_ERR : SIG_HOLD; + } + + /* No.. then signal can handle the other cases */ + + else + { + /* Set the signal handler disposition */ + + disposition = signal(signo, func); + if (disposition != SIG_ERR) + { + /* And unblock the signal */ + + ret = sigprocmask(SIG_UNBLOCK, &set, NULL); + if (ret < 0) + { + /* Restore the original signal disposition and return and + * error. + */ + + (void)signal(signo, disposition); + disposition = SIG_ERR; + } + } + } + + return disposition; +} diff --git a/libc/signal/signal.c b/libc/signal/signal.c index fed1b55abd0..e7df89ce292 100644 --- a/libc/signal/signal.c +++ b/libc/signal/signal.c @@ -37,7 +37,10 @@ * Included Files ****************************************************************************/ +#include + #include +#include /**************************************************************************** * Public Functions @@ -50,29 +53,20 @@ * The signal() function will modify signal dispositions. The 'signo' * argument specifies the signal. The 'func' argument specifies the * signal's disposition, which may be SIG_DFL, SIG_IGN, or the address - * of a signal handler. If 'func' is the address of a signal handler, the + * of a signal handler. If 'func' is the address of a signal handler, the * system will add 'signo' to the calling process' signal mask before * executing the signal handler; when the signal handler returns, the * system will restore the calling process' signal mask to its state prior - * to the delivery of the signal. 'signo' will be removed from the calling - * process' signal mask. - * - * NOTE: The value SIG_HOLD for 'func' is not supported. It should work - * like this: If 'func' is equal to SIG_HOLD, 'signo' will be added to, - * not removed from, the calling process' signal mask and 'signo''s - * disposition will remain unchanged. + * to the delivery of the signal. * * Input Parameters: * signo - Identifies the signal to operate on * func - The new disposition of the signal * * Returned Value: - * Upon successful completion, signal() will the previous disposition of - * the signal. Otherwise, SIG_ERR will be returned and errno set to - * indicate the error. - * - * NOTE: signal() would return SIG_HOLD if the signal had been blocked and - * the signal's previous disposition if it had not been blocked. + * Upon successful completion, signal() will return the previous + * disposition of the signal handling. Otherwise, SIG_ERR will be returned + * and errno set to indicate the nature of the error. * ****************************************************************************/ @@ -82,6 +76,9 @@ CODE void (*signal(int signo, CODE void (*func)(int signo)))(int signo) struct sigaction oact; int ret; + DEBUGASSERT(GOOD_SIGNO(signo) && func != NULL); + DEBUGASSERT(func != SIG_ERR && func != SIG_HOLD); + /* Initialize the sigaction structure */ act.sa_handler = func;