diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index 8c7cf8c0b99a..0e7f71cdf721 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -51,7 +51,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_JUMP `, yes, :ref:`POSIX_C_LANG_SUPPORT `, yes, :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` - :ref:`POSIX_SIGNALS `,, :kconfig:option:`CONFIG_POSIX_SIGNALS` + :ref:`POSIX_SIGNALS `, yes, :kconfig:option:`CONFIG_POSIX_SIGNALS` :ref:`†` :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` :ref:`XSI_THREADS_EXT `, yes, :kconfig:option:`CONFIG_XSI_THREADS_EXT` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index 5526b7b1a1a8..d227c9c2233d 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -450,31 +450,36 @@ POSIX_SIGNAL_JUMP POSIX_SIGNALS +++++++++++++ -Signal services are a basic mechanism within POSIX-based systems and are -required for error and event handling. - Enable this option group with :kconfig:option:`CONFIG_POSIX_SIGNALS`. +.. note:: + As processes are not yet supported in Zephyr, the ISO C functions ``abort()``, ``signal()``, + and ``raise()``, as well as the other POSIX functions listed below, may exhibit undefined + behaviour. The POSIX functions ``kill()``, ``pause()``, ``sigaction()``, ``sigpending()``, + ``sigsuspend()``, and ``sigwait()`` are implemented to ensure that conformant applications can + link, but they are expected to fail, setting errno to ``ENOSYS`` + :ref:`†`. + .. csv-table:: POSIX_SIGNALS :header: API, Supported :widths: 50,10 - abort(),yes - alarm(), - kill(), - pause(), - raise(), - sigaction(), + abort(),yes :ref:`†` + alarm(),yes :ref:`†` + kill(),yes :ref:`†` + pause(),yes :ref:`†` + raise(),yes :ref:`†` + sigaction(),yes :ref:`†` sigaddset(),yes sigdelset(),yes sigemptyset(),yes sigfillset(),yes sigismember(),yes - signal(), - sigpending(), + signal(),yes :ref:`†` + sigpending(),yes :ref:`†` sigprocmask(),yes - sigsuspend(), - sigwait(), + sigsuspend(),yes :ref:`†` + sigwait(),yes :ref:`†` strsignal(),yes .. _posix_option_group_single_process: diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index 165050f2ded9..11cbe726dadb 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -77,6 +77,16 @@ typedef struct { #define SIG_UNBLOCK 2 #endif +#define SIG_DFL ((void *)0) +#define SIG_IGN ((void *)1) +#define SIG_ERR ((void *)-1) + +#define SI_USER 1 +#define SI_QUEUE 2 +#define SI_TIMER 3 +#define SI_ASYNCIO 4 +#define SI_MESGQ 5 + typedef int sig_atomic_t; /* Atomic entity type (ANSI) */ union sigval { @@ -92,12 +102,36 @@ struct sigevent { int sigev_signo; }; +typedef struct { + int si_signo; + int si_code; + union sigval si_value; +} siginfo_t; + +struct sigaction { + void (*sa_handler)(int signno); + sigset_t sa_mask; + int sa_flags; + void (*sa_sigaction)(int signo, siginfo_t *info, void *context); +}; + +typedef void (*sighandler_t)(int signo); + +unsigned int alarm(unsigned int seconds); +int kill(pid_t pid, int sig); +int pause(void); +int raise(int signo); +int sigaction(int sig, const struct sigaction *ZRESTRICT act, struct sigaction *ZRESTRICT oact); +int sigpending(sigset_t *set); +int sigsuspend(const sigset_t *sigmask); +int sigwait(const sigset_t *ZRESTRICT set, int *ZRESTRICT signo); char *strsignal(int signum); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); int sigismember(const sigset_t *set, int signo); +sighandler_t signal(int signo, sighandler_t handler); int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 4b42e0a150c9..7d793848f99b 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -105,6 +105,7 @@ config NEWLIB_LIBC imply POSIX_FD_MGMT_ALIAS_LSEEK imply POSIX_FILE_SYSTEM_ALIAS_FSTAT imply POSIX_MULTI_PROCESS_ALIAS_GETPID + imply POSIX_SIGNALS_ALIAS_KILL help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index 4507302e3f32..1e84a55de598 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -24,6 +24,7 @@ endif # POSIX_REALTIME_SIGNALS config POSIX_SIGNALS bool "POSIX signals [EXPERIMENTAL]" select EXPERIMENTAL + select POSIX_MULTI_PROCESS help Enable support for POSIX signals. @@ -36,6 +37,12 @@ config POSIX_SIGNAL_STRING_DESC Use full description for the strsignal API. Will use 256 bytes of ROM. +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_SIGNALS_ALIAS_KILL + bool + endif endmenu # "Signal support" diff --git a/lib/posix/options/multi_process.c b/lib/posix/options/multi_process.c index 221dc04ae1ad..ab697a66c0c7 100644 --- a/lib/posix/options/multi_process.c +++ b/lib/posix/options/multi_process.c @@ -21,3 +21,6 @@ pid_t getpid(void) return 42; } +#ifdef CONFIG_POSIX_MULTI_PROCESS_ALIAS_GETPID +FUNC_ALIAS(getpid, _getpid, pid_t); +#endif /* CONFIG_POSIX_MULTI_PROCESS_ALIAS_GETPID */ diff --git a/lib/posix/options/signal.c b/lib/posix/options/signal.c index cb282f69bdc8..84171fde0f07 100644 --- a/lib/posix/options/signal.c +++ b/lib/posix/options/signal.c @@ -118,3 +118,62 @@ int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset errno = ENOSYS; return -1; } + +/* + * The functions below are provided so that conformant POSIX applications and libraries can still + * link. + */ + +unsigned int alarm(unsigned int seconds) +{ + ARG_UNUSED(seconds); + return 0; +} + +int kill(pid_t pid, int sig) +{ + ARG_UNUSED(pid); + ARG_UNUSED(sig); + errno = ENOSYS; + return -1; +} +#ifdef CONFIG_POSIX_SIGNALS_ALIAS_KILL +FUNC_ALIAS(kill, _kill, int); +#endif /* CONFIG_POSIX_SIGNALS_ALIAS_KILL */ + +int pause(void) +{ + errno = ENOSYS; + return -1; +} + +int sigaction(int sig, const struct sigaction *ZRESTRICT act, struct sigaction *ZRESTRICT oact) +{ + ARG_UNUSED(sig); + ARG_UNUSED(act); + ARG_UNUSED(oact); + errno = ENOSYS; + return -1; +} + +int sigpending(sigset_t *set) +{ + ARG_UNUSED(set); + errno = ENOSYS; + return -1; +} + +int sigsuspend(const sigset_t *sigmask) +{ + ARG_UNUSED(sigmask); + errno = ENOSYS; + return -1; +} + +int sigwait(const sigset_t *ZRESTRICT set, int *ZRESTRICT sig) +{ + ARG_UNUSED(set); + ARG_UNUSED(sig); + errno = ENOSYS; + return -1; +} diff --git a/tests/posix/headers/src/signal_h.c b/tests/posix/headers/src/signal_h.c index 35616e4a29e5..76cde3e592d9 100644 --- a/tests/posix/headers/src/signal_h.c +++ b/tests/posix/headers/src/signal_h.c @@ -6,6 +6,8 @@ #include "_common.h" +#include + #ifdef CONFIG_POSIX_API #include #else @@ -19,13 +21,17 @@ */ ZTEST(posix_headers, test_signal_h) { - /* zassert_not_equal(-1, SIG_DFL); */ /* not implemented */ - /* zassert_not_equal(-1, SIG_ERR); */ /* not implemented */ + typedef void *(*my_sig_handler_t)(int signo); + + my_sig_handler_t handler; + + handler = SIG_DFL; + handler = SIG_ERR; + handler = SIG_IGN; /* zassert_not_equal(-1, SIG_HOLD); */ /* not implemented */ - /* zassert_not_equal(-1, SIG_IGN); */ /* not implemented */ zassert_not_equal((sig_atomic_t)-1, (sig_atomic_t)0); - /* zassert_not_equal((pid_t)-1, (pid_t)0); */ /* not implemented */ + zassert_not_equal((pid_t)-1, (pid_t)0); zassert_not_equal(-1, offsetof(struct sigevent, sigev_notify)); zassert_not_equal(-1, offsetof(struct sigevent, sigev_signo)); @@ -47,6 +53,15 @@ ZTEST(posix_headers, test_signal_h) zassert_not_equal(-1, SIG_UNBLOCK); zassert_not_equal(-1, SIG_SETMASK); + zassert_not_equal(-1, offsetof(struct sigaction, sa_handler)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_mask)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_flags)); + zassert_not_equal(-1, offsetof(struct sigaction, sa_sigaction)); + + zassert_not_equal(-1, offsetof(siginfo_t, si_signo)); + zassert_not_equal(-1, offsetof(siginfo_t, si_code)); + zassert_not_equal(-1, offsetof(siginfo_t, si_value)); + /* zassert_not_equal(-1, SA_NOCLDSTOP); */ /* not implemented */ /* zassert_not_equal(-1, SA_ONSTACK); */ /* not implemented */ /* zassert_not_equal(-1, SA_RESETHAND); */ /* not implemented */ @@ -117,18 +132,11 @@ ZTEST(posix_headers, test_signal_h) /* zassert_not_equal(-1, CLD_STOPPED); */ /* not implemented */ /* zassert_not_equal(-1, CLD_CONTINUED); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_IN); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_OUT); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_MSG); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_ERR); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_PRI); */ /* not implemented */ - /* zassert_not_equal(-1, POLL_HUP); */ /* not implemented */ - - /* zassert_not_equal(-1, SI_USER); */ /* not implemented */ - /* zassert_not_equal(-1, SI_QUEUE); */ /* not implemented */ - /* zassert_not_equal(-1, SI_TIMER); */ /* not implemented */ - /* zassert_not_equal(-1, SI_ASYNCIO); */ /* not implemented */ - /* zassert_not_equal(-1, SI_MESGQ); */ /* not implemented */ + zassert_not_equal(-1, SI_USER); + zassert_not_equal(-1, SI_QUEUE); + zassert_not_equal(-1, SI_TIMER); + zassert_not_equal(-1, SI_ASYNCIO); + zassert_not_equal(-1, SI_MESGQ); #ifdef CONFIG_POSIX_SIGNALS zassert_true(SIGRTMIN >= 0); @@ -158,37 +166,40 @@ ZTEST(posix_headers, test_signal_h) zassert_not_equal(-1, SIGXCPU); zassert_not_equal(-1, SIGXFSZ); zassert_not_equal(((sigset_t){.sig[0] = 0}).sig[0], ((sigset_t){.sig[0] = -1}).sig[0]); - zassert_not_null(sigemptyset); - zassert_not_null(sigfillset); + zassert_not_null(abort); + zassert_not_null(alarm); + zassert_not_null(kill); + zassert_not_null(pause); + zassert_not_null(pthread_sigmask); + zassert_not_null(raise); + zassert_not_null(sigaction); zassert_not_null(sigaddset); zassert_not_null(sigdelset); + zassert_not_null(sigemptyset); + zassert_not_null(sigfillset); zassert_not_null(sigismember); - zassert_not_null(strsignal); + zassert_not_null(signal); + zassert_not_null(sigpending); zassert_not_null(sigprocmask); - zassert_not_null(pthread_sigmask); + zassert_not_null(sigsuspend); + zassert_not_null(sigwait); + zassert_not_null(strsignal); #endif /* CONFIG_POSIX_SIGNALS */ if (IS_ENABLED(CONFIG_POSIX_API)) { - /* zassert_not_null(kill); */ /* not implemented */ /* zassert_not_null(killpg); */ /* not implemented */ /* zassert_not_null(psiginfo); */ /* not implemented */ /* zassert_not_null(psignal); */ /* not implemented */ /* zassert_not_null(pthread_kill); */ /* not implemented */ - /* zassert_not_null(raise); */ /* not implemented */ - /* zassert_not_null(sigaction); */ /* not implemented */ /* zassert_not_null(sigaltstack); */ /* not implemented */ /* zassert_not_null(sighold); */ /* not implemented */ /* zassert_not_null(sigignore); */ /* not implemented */ /* zassert_not_null(siginterrupt); */ /* not implemented */ - /* zassert_not_null(signal); */ /* not implemented */ /* zassert_not_null(sigpause); */ /* not implemented */ - /* zassert_not_null(sigpending); */ /* not implemented */ /* zassert_not_null(sigqueue); */ /* not implemented */ /* zassert_not_null(sigrelse); */ /* not implemented */ /* zassert_not_null(sigset); */ /* not implemented */ - /* zassert_not_null(sigsuspend); */ /* not implemented */ /* zassert_not_null(sigtimedwait); */ /* not implemented */ - /* zassert_not_null(sigwait); */ /* not implemented */ /* zassert_not_null(sigwaitinfo); */ /* not implemented */ } }