dc3270f14e
This change introduces the `lwp_signal_kill_all` function, which allows a signal to be sent to all processes in the system. The function iterates over all PIDs and sends the specified signal to each process, except those that are protected from signals. This enhancement provides a convenient way to broadcast signals across all processes in the system. Changes: - Added `lwp_signal_kill_all` function in `lwp_signal.c` to broadcast a signal to all processes by iterating over all PIDs using the existing `lwp_pid_for_each` function. - Introduced a new `kill_all_param` structure to encapsulate the signal information needed for killing processes. - Added internal `_kill_each` helper function for sending the signal to each PID. - Updated `lwp_signal.h` with the new function prototype for `lwp_signal_kill_all`. - Modified `sys_kill` in `lwp_syscall.c` to call `lwp_signal_kill_all` when a process is not specified. Signed-off-by: Shell <smokewood@qq.com>
239 lines
6.8 KiB
C
239 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2020-02-23 Jesven first version.
|
|
* 2023-07-06 Shell update the generation, pending and delivery API
|
|
* 2023-11-22 Shell support for job control signal
|
|
*/
|
|
|
|
#ifndef __LWP_SIGNAL_H__
|
|
#define __LWP_SIGNAL_H__
|
|
|
|
#include "syscall_generic.h"
|
|
|
|
#include <rtthread.h>
|
|
#include <sys/signal.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define _USIGNAL_SIGMASK(signo) (1u << ((signo)-1))
|
|
#define LWP_SIG_NO_IGN_SET \
|
|
(_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
|
|
_USIGNAL_SIGMASK(SIGKILL))
|
|
#define LWP_SIG_IGNORE_SET \
|
|
(_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG) | \
|
|
_USIGNAL_SIGMASK(SIGWINCH) /* from 4.3 BSD, not POSIX.1 */)
|
|
#define LWP_SIG_JOBCTL_SET \
|
|
(_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
|
|
_USIGNAL_SIGMASK(SIGTSTP) | _USIGNAL_SIGMASK(SIGTTIN) | \
|
|
_USIGNAL_SIGMASK(SIGTTOU))
|
|
#define LWP_SIG_STOP_SET \
|
|
(_USIGNAL_SIGMASK(SIGSTOP) | _USIGNAL_SIGMASK(SIGTSTP) | \
|
|
_USIGNAL_SIGMASK(SIGTTIN) | _USIGNAL_SIGMASK(SIGTTOU))
|
|
#define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
|
|
#define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
|
|
#define LWP_SIG_USER_SA_FLAGS \
|
|
(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
|
|
SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS)
|
|
#define LWP_SIG_INVALID_TIMER ((timer_t)-1)
|
|
|
|
typedef enum
|
|
{
|
|
LWP_SIG_MASK_CMD_BLOCK,
|
|
LWP_SIG_MASK_CMD_UNBLOCK,
|
|
LWP_SIG_MASK_CMD_SET_MASK,
|
|
__LWP_SIG_MASK_CMD_WATERMARK
|
|
} lwp_sig_mask_cmd_t;
|
|
|
|
/**
|
|
* LwP implementation of POSIX signal
|
|
*/
|
|
struct lwp_signal
|
|
{
|
|
timer_t real_timer;
|
|
struct lwp_sigqueue sig_queue;
|
|
rt_thread_t sig_dispatch_thr[_LWP_NSIG];
|
|
|
|
lwp_sighandler_t sig_action[_LWP_NSIG];
|
|
lwp_sigset_t sig_action_mask[_LWP_NSIG];
|
|
|
|
lwp_sigset_t sig_action_nodefer;
|
|
lwp_sigset_t sig_action_onstack;
|
|
lwp_sigset_t sig_action_restart;
|
|
lwp_sigset_t sig_action_siginfo;
|
|
lwp_sigset_t sig_action_nocldstop;
|
|
lwp_sigset_t sig_action_nocldwait;
|
|
};
|
|
|
|
struct rt_lwp;
|
|
struct rt_processgroup;
|
|
|
|
#ifndef ARCH_MM_MMU
|
|
void lwp_sighandler_set(int sig, lwp_sighandler_t func);
|
|
void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func);
|
|
#endif
|
|
|
|
rt_inline void lwp_sigqueue_init(lwp_sigqueue_t sigq)
|
|
{
|
|
rt_memset(&sigq->sigset_pending, 0, sizeof(lwp_sigset_t));
|
|
rt_list_init(&sigq->siginfo_list);
|
|
}
|
|
|
|
/**
|
|
* @brief release the signal queue
|
|
*
|
|
* @param sigq target signal queue
|
|
*/
|
|
void lwp_sigqueue_clear(lwp_sigqueue_t sigq);
|
|
|
|
rt_err_t lwp_signal_init(struct lwp_signal *sig);
|
|
|
|
rt_err_t lwp_signal_detach(struct lwp_signal *signal);
|
|
|
|
rt_inline void lwp_thread_signal_detach(struct lwp_thread_signal *tsig)
|
|
{
|
|
lwp_sigqueue_clear(&tsig->sig_queue);
|
|
}
|
|
|
|
/**
|
|
* @brief send a signal to the process
|
|
*
|
|
* @param lwp the process to be killed
|
|
* @param signo the signal number
|
|
* @param code as in siginfo
|
|
* @param value as in siginfo
|
|
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
|
* successful
|
|
*
|
|
* @note the *signal_kill have the same definition of a successful return as
|
|
* kill() in IEEE Std 1003.1-2017
|
|
*/
|
|
rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code,
|
|
lwp_siginfo_ext_t value);
|
|
|
|
/**
|
|
* @brief set or examine the signal action of signo
|
|
*
|
|
* @param signo signal number
|
|
* @param act the signal action
|
|
* @param oact the old signal action
|
|
* @return rt_err_t
|
|
*/
|
|
rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo,
|
|
const struct lwp_sigaction *restrict act,
|
|
struct lwp_sigaction *restrict oact);
|
|
|
|
/**
|
|
* @brief send a signal to the thread
|
|
*
|
|
* @param thread target thread
|
|
* @param signo the signal number
|
|
* @param code as in siginfo
|
|
* @param value as in siginfo
|
|
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
|
* successful
|
|
*/
|
|
rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code,
|
|
lwp_siginfo_ext_t value);
|
|
|
|
/**
|
|
* @brief set signal mask of target thread
|
|
*
|
|
* @param thread the target thread
|
|
* @param how command
|
|
* @param sigset operand
|
|
* @param oset the address to old set
|
|
* @return rt_err_t
|
|
*/
|
|
rt_err_t lwp_thread_signal_mask(rt_thread_t thread, lwp_sig_mask_cmd_t how,
|
|
const lwp_sigset_t *sigset, lwp_sigset_t *oset);
|
|
|
|
/**
|
|
* @brief Catch signal if exists and no return, otherwise return with no
|
|
* side effect
|
|
*
|
|
* @param exp_frame the exception frame on kernel stack
|
|
*/
|
|
void lwp_thread_signal_catch(void *exp_frame);
|
|
|
|
/**
|
|
* @brief Check if it's okay to suspend for current lwp thread
|
|
*
|
|
* @param thread target thread
|
|
* @param suspend_flag suspend flag of target thread
|
|
* @return int 1 if can be suspended, otherwise not
|
|
*/
|
|
int lwp_thread_signal_suspend_check(rt_thread_t thread, int suspend_flag);
|
|
|
|
/**
|
|
* @brief Asynchronously wait for signal
|
|
*
|
|
* @param thread target thread
|
|
* @param sigset the signals to be waited
|
|
* @param info address of user siginfo
|
|
* @param timeout timeout of waiting
|
|
* @return rt_err_t
|
|
*/
|
|
rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
|
|
siginfo_t *usi, struct timespec *timeout);
|
|
|
|
/**
|
|
* @brief Examine the set of signals that are blocked from delivery to the
|
|
* calling thread and that are pending on the process or the calling thread
|
|
*
|
|
* @param thread target thread
|
|
* @param sigset where mask of pending signals is returned
|
|
*/
|
|
void lwp_thread_signal_pending(rt_thread_t thread, lwp_sigset_t *sigset);
|
|
|
|
/**
|
|
* @brief send a signal to the process group
|
|
*
|
|
* @param pgrp target process group
|
|
* @param signo the signal number
|
|
* @param code as in siginfo
|
|
* @param value as in siginfo
|
|
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
|
* successful
|
|
*/
|
|
rt_err_t lwp_pgrp_signal_kill(struct rt_processgroup *pgrp, long signo,
|
|
long code, lwp_siginfo_ext_t value);
|
|
|
|
rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig)
|
|
{
|
|
unsigned long sig = _sig - 1;
|
|
|
|
if (_LWP_NSIG_WORDS == 1)
|
|
{
|
|
return 1 & (set->sig[0] >> sig);
|
|
}
|
|
else
|
|
{
|
|
return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
|
|
}
|
|
}
|
|
|
|
struct itimerspec;
|
|
|
|
rt_bool_t lwp_sigisign(struct rt_lwp *lwp, int _sig);
|
|
|
|
rt_err_t lwp_signal_setitimer(struct rt_lwp *lwp, int which,
|
|
const struct itimerspec *restrict new,
|
|
struct itimerspec *restrict old);
|
|
|
|
rt_bool_t lwp_signal_restart_syscall(struct rt_lwp *lwp, int error_code);
|
|
|
|
rt_err_t lwp_signal_kill_all(long signo, long code, lwp_siginfo_ext_t value);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __LWP_SIGNAL_H__ */
|