libc: local signal delivery via 'kill'

This patch adds the ability to call 'kill' with the own PID to trigger
the execution of the handler of the specified POSIX signal. This is used
by 'bash', e.g., when cancelling the input of a command via control-c.

Related to issue #3546
This commit is contained in:
Norman Feske 2019-10-30 22:19:54 +01:00 committed by Christian Helmuth
parent c1012e6a45
commit bb6eb0f6ea
4 changed files with 29 additions and 2 deletions

View File

@ -116,7 +116,6 @@ DUMMY(int , -1, getpriority, (int, int))
DUMMY(int , -1, getrusage, (int, rusage *))
DUMMY(uid_t , 0, getuid, (void))
DUMMY_SILENT(int , 1, isatty, (int))
DUMMY(int , -1, kill, (pid_t, int))
DUMMY(int , -1, link, (const char *, const char *))
DUMMY(int , 0, minherit, (void *, size_t, int))
DUMMY(int , -1, mknod, (const char *, mode_t, dev_t))

View File

@ -128,7 +128,7 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
void _handle_user_interrupt();
Signal _signal;
Signal _signal { _pid };
Reconstructible<Io_signal_handler<Kernel>> _resume_main_handler {
_env.ep(), *this, &Kernel::_resume_main };

View File

@ -58,8 +58,12 @@ struct Libc::Signal : Noncopyable
unsigned _nesting_level = 0;
pid_t const _local_pid;
public:
Signal(pid_t local_pid) : _local_pid(local_pid) { }
void charge(unsigned n)
{
if (n > NSIG)
@ -103,6 +107,11 @@ struct Libc::Signal : Noncopyable
* occurred during a blocking operation ('select').
*/
unsigned count() const { return _count; }
/**
* Return true if specified PID belongs to the process itself
*/
bool local_pid(pid_t pid) const { return pid == _local_pid; }
};
#endif /* _LIBC__INTERNAL__SIGNAL_H_ */

View File

@ -25,6 +25,7 @@ extern "C" {
#include <internal/types.h>
#include <internal/init.h>
#include <internal/signal.h>
#include <internal/errno.h>
using namespace Libc;
@ -135,6 +136,24 @@ extern "C" int __sys_sigaction(int, const struct sigaction *, struct sigaction
extern "C" int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((weak, alias("sigaction")));
extern "C" int kill(pid_t pid, int signum)
{
if (_signal_ptr->local_pid(pid)) {
_signal_ptr->charge(signum);
_signal_ptr->execute_signal_handlers();
return 0;
} else {
warning("submitting signals to remote processes via 'kill' not supported");
return Libc::Errno(EPERM);
}
}
extern "C" int _kill(pid_t, int) __attribute__((weak, alias("kill")));
extern "C" int __sys_kill(pid_t, int) __attribute__((weak, alias("kill")));
extern "C" int __libc_kill(pid_t, int) __attribute__((weak, alias("kill")));
extern "C" pid_t wait(int *istat) {
return wait4(WAIT_ANY, istat, 0, NULL); }