2000-02-18 03:39:52 +08:00
|
|
|
/*
|
|
|
|
FUNCTION
|
|
|
|
<<signal>>---specify handler subroutine for a signal
|
|
|
|
|
|
|
|
INDEX
|
|
|
|
signal
|
|
|
|
INDEX
|
|
|
|
_signal_r
|
|
|
|
|
2017-11-30 15:43:14 +08:00
|
|
|
SYNOPSIS
|
2000-02-18 03:39:52 +08:00
|
|
|
#include <signal.h>
|
2005-10-29 05:21:08 +08:00
|
|
|
void (*signal(int <[sig]>, void(*<[func]>)(int))) (int);
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2005-10-29 05:21:08 +08:00
|
|
|
void (*_signal_r(void *<[reent]>, int <[sig]>, void(*<[func]>)(int))) (int);
|
2000-02-18 03:39:52 +08:00
|
|
|
|
|
|
|
DESCRIPTION
|
2005-10-29 05:21:08 +08:00
|
|
|
<<signal>> provides a simple signal-handling implementation for embedded
|
2000-02-18 03:39:52 +08:00
|
|
|
targets.
|
|
|
|
|
|
|
|
<<signal>> allows you to request changed treatment for a particular
|
|
|
|
signal <[sig]>. You can use one of the predefined macros <<SIG_DFL>>
|
|
|
|
(select system default handling) or <<SIG_IGN>> (ignore this signal)
|
|
|
|
as the value of <[func]>; otherwise, <[func]> is a function pointer
|
|
|
|
that identifies a subroutine in your program as the handler for this signal.
|
|
|
|
|
|
|
|
Some of the execution environment for signal handlers is
|
|
|
|
unpredictable; notably, the only library function required to work
|
2005-10-29 05:21:08 +08:00
|
|
|
correctly from within a signal handler is <<signal>> itself, and
|
2000-02-18 03:39:52 +08:00
|
|
|
only when used to redefine the handler for the current signal value.
|
|
|
|
|
|
|
|
Static storage is likewise unreliable for signal handlers, with one
|
|
|
|
exception: if you declare a static storage location as `<<volatile
|
|
|
|
sig_atomic_t>>', then you may use that location in a signal handler to
|
|
|
|
store signal values.
|
|
|
|
|
|
|
|
If your signal handler terminates using <<return>> (or implicit
|
|
|
|
return), your program's execution continues at the point
|
|
|
|
where it was when the signal was raised (whether by your program
|
|
|
|
itself, or by an external event). Signal handlers can also
|
|
|
|
use functions such as <<exit>> and <<abort>> to avoid returning.
|
|
|
|
|
2005-10-29 05:21:08 +08:00
|
|
|
The alternate function <<_signal_r>> is the reentrant version.
|
2000-02-18 03:39:52 +08:00
|
|
|
The extra argument <[reent]> is a pointer to a reentrancy structure.
|
|
|
|
|
|
|
|
@c FIXME: do we have setjmp.h and assoc fns?
|
|
|
|
|
|
|
|
RETURNS
|
|
|
|
If your request for a signal handler cannot be honored, the result is
|
|
|
|
<<SIG_ERR>>; a specific error number is also recorded in <<errno>>.
|
|
|
|
|
|
|
|
Otherwise, the result is the previous handler (a function pointer or
|
|
|
|
one of the predefined macros).
|
|
|
|
|
|
|
|
PORTABILITY
|
2005-10-29 05:21:08 +08:00
|
|
|
ANSI C requires <<signal>>.
|
2000-02-18 03:39:52 +08:00
|
|
|
|
|
|
|
No supporting OS subroutines are required to link with <<signal>>, but
|
|
|
|
it will not have any useful effects, except for software generated signals,
|
|
|
|
without an operating system that can actually raise exceptions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* signal.c
|
|
|
|
* Original Author: G. Haley
|
|
|
|
*
|
|
|
|
* signal associates the function pointed to by func with the signal sig. When
|
|
|
|
* a signal occurs, the value of func determines the action taken as follows:
|
|
|
|
* if func is SIG_DFL, the default handling for that signal will occur; if func
|
|
|
|
* is SIG_IGN, the signal will be ignored; otherwise, the default handling for
|
|
|
|
* the signal is restored (SIG_DFL), and the function func is called with sig
|
|
|
|
* as its argument. Returns the value of func for the previous call to signal
|
|
|
|
* for the signal sig, or SIG_ERR if the request fails.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* _init_signal initialises the signal handlers for each signal. This function
|
|
|
|
is called by crt0 at program startup. */
|
|
|
|
|
|
|
|
#ifdef SIGNAL_PROVIDED
|
|
|
|
|
|
|
|
int _dummy_simulated_signal;
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <reent.h>
|
|
|
|
#include <_syslist.h>
|
|
|
|
|
Add --enable-newlib-reent-thread-local option
By default, Newlib uses a huge object of type struct _reent to store
thread-specific data. This object is returned by __getreent() if the
__DYNAMIC_REENT__ Newlib configuration option is defined.
The reentrancy structure contains for example errno and the standard input,
output, and error file streams. This means that if an application only uses
errno it has a dependency on the file stream support even if it does not use
it. This is an issue for lower end targets and applications which need to
qualify the software according to safety standards (for example ECSS-E-ST-40C,
ECSS-Q-ST-80C, IEC 61508, ISO 26262, DO-178, DO-330, DO-333).
If the new _REENT_THREAD_LOCAL configuration option is enabled, then struct
_reent is replaced by dedicated thread-local objects for each struct _reent
member. The thread-local objects are defined in translation units which use
the corresponding object.
2022-05-16 17:51:54 +08:00
|
|
|
#ifdef _REENT_THREAD_LOCAL
|
|
|
|
_Thread_local void (**_tls_sig_func)(int);
|
|
|
|
#endif
|
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
int
|
2017-12-04 11:43:30 +08:00
|
|
|
_init_signal_r (struct _reent *ptr)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
if (_REENT_SIG_FUNC(ptr) == NULL)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
2022-02-04 18:47:18 +08:00
|
|
|
_REENT_SIG_FUNC(ptr) = (_sig_func_ptr *)_malloc_r (ptr, sizeof (_sig_func_ptr) * NSIG);
|
|
|
|
if (_REENT_SIG_FUNC(ptr) == NULL)
|
2000-02-18 03:39:52 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0; i < NSIG; i++)
|
2022-02-04 18:47:18 +08:00
|
|
|
_REENT_SIG_FUNC(ptr)[i] = SIG_DFL;
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
_sig_func_ptr
|
2017-12-04 11:43:30 +08:00
|
|
|
_signal_r (struct _reent *ptr,
|
2017-12-04 09:31:41 +08:00
|
|
|
int sig,
|
2000-02-18 03:39:52 +08:00
|
|
|
_sig_func_ptr func)
|
|
|
|
{
|
2000-04-18 01:10:18 +08:00
|
|
|
_sig_func_ptr old_func;
|
2000-02-18 03:39:52 +08:00
|
|
|
|
|
|
|
if (sig < 0 || sig >= NSIG)
|
|
|
|
{
|
2022-01-18 17:13:04 +08:00
|
|
|
_REENT_ERRNO(ptr) = EINVAL;
|
2000-02-18 03:39:52 +08:00
|
|
|
return SIG_ERR;
|
|
|
|
}
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
if (_REENT_SIG_FUNC(ptr) == NULL && _init_signal_r (ptr) != 0)
|
2000-02-18 03:39:52 +08:00
|
|
|
return SIG_ERR;
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
old_func = _REENT_SIG_FUNC(ptr)[sig];
|
|
|
|
_REENT_SIG_FUNC(ptr)[sig] = func;
|
2000-02-18 03:39:52 +08:00
|
|
|
|
|
|
|
return old_func;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-12-04 11:43:30 +08:00
|
|
|
_raise_r (struct _reent *ptr,
|
2003-06-07 03:57:51 +08:00
|
|
|
int sig)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
_sig_func_ptr func;
|
|
|
|
|
|
|
|
if (sig < 0 || sig >= NSIG)
|
|
|
|
{
|
2022-01-18 17:13:04 +08:00
|
|
|
_REENT_ERRNO(ptr) = EINVAL;
|
2000-02-18 03:39:52 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
if (_REENT_SIG_FUNC(ptr) == NULL)
|
2007-11-01 06:22:31 +08:00
|
|
|
func = SIG_DFL;
|
|
|
|
else
|
2022-02-04 18:47:18 +08:00
|
|
|
func = _REENT_SIG_FUNC(ptr)[sig];
|
2007-11-01 06:22:31 +08:00
|
|
|
|
2000-09-20 03:39:45 +08:00
|
|
|
if (func == SIG_DFL)
|
|
|
|
return _kill_r (ptr, _getpid_r (ptr), sig);
|
|
|
|
else if (func == SIG_IGN)
|
|
|
|
return 0;
|
|
|
|
else if (func == SIG_ERR)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
2022-01-18 17:13:04 +08:00
|
|
|
_REENT_ERRNO(ptr) = EINVAL;
|
2000-09-20 03:39:45 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-02-04 18:47:18 +08:00
|
|
|
_REENT_SIG_FUNC(ptr)[sig] = SIG_DFL;
|
2000-02-18 03:39:52 +08:00
|
|
|
func (sig);
|
2000-09-20 03:39:45 +08:00
|
|
|
return 0;
|
2000-02-18 03:39:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-12-04 11:43:30 +08:00
|
|
|
__sigtramp_r (struct _reent *ptr,
|
2003-06-07 03:57:51 +08:00
|
|
|
int sig)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
_sig_func_ptr func;
|
|
|
|
|
|
|
|
if (sig < 0 || sig >= NSIG)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
if (_REENT_SIG_FUNC(ptr) == NULL && _init_signal_r (ptr) != 0)
|
2000-02-18 03:39:52 +08:00
|
|
|
return -1;
|
|
|
|
|
2022-02-04 18:47:18 +08:00
|
|
|
func = _REENT_SIG_FUNC(ptr)[sig];
|
2000-09-20 03:39:45 +08:00
|
|
|
if (func == SIG_DFL)
|
|
|
|
return 1;
|
|
|
|
else if (func == SIG_ERR)
|
|
|
|
return 2;
|
|
|
|
else if (func == SIG_IGN)
|
|
|
|
return 3;
|
|
|
|
else
|
|
|
|
{
|
2022-02-04 18:47:18 +08:00
|
|
|
_REENT_SIG_FUNC(ptr)[sig] = SIG_DFL;
|
2000-02-18 03:39:52 +08:00
|
|
|
func (sig);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _REENT_ONLY
|
|
|
|
|
|
|
|
int
|
2017-12-04 11:43:30 +08:00
|
|
|
raise (int sig)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
return _raise_r (_REENT, sig);
|
|
|
|
}
|
|
|
|
|
|
|
|
_sig_func_ptr
|
2017-12-04 11:43:30 +08:00
|
|
|
signal (int sig,
|
2000-02-18 03:39:52 +08:00
|
|
|
_sig_func_ptr func)
|
|
|
|
{
|
|
|
|
return _signal_r (_REENT, sig, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-12-04 11:00:43 +08:00
|
|
|
_init_signal (void)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
return _init_signal_r (_REENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2017-12-04 11:43:30 +08:00
|
|
|
__sigtramp (int sig)
|
2000-02-18 03:39:52 +08:00
|
|
|
{
|
|
|
|
return __sigtramp_r (_REENT, sig);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* !SIGNAL_PROVIDED */
|