From bb6eb0f6ea072e12cdfe73883b695a2158bc3061 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 30 Oct 2019 22:19:54 +0100 Subject: [PATCH] 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 --- repos/libports/src/lib/libc/dummies.cc | 1 - repos/libports/src/lib/libc/internal/kernel.h | 2 +- repos/libports/src/lib/libc/internal/signal.h | 9 +++++++++ repos/libports/src/lib/libc/signal.cc | 19 +++++++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/repos/libports/src/lib/libc/dummies.cc b/repos/libports/src/lib/libc/dummies.cc index d3321d6def..6b461b96d7 100644 --- a/repos/libports/src/lib/libc/dummies.cc +++ b/repos/libports/src/lib/libc/dummies.cc @@ -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)) diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index 06cbeb6dc9..57dcaf2936 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -128,7 +128,7 @@ struct Libc::Kernel final : Vfs::Io_response_handler, void _handle_user_interrupt(); - Signal _signal; + Signal _signal { _pid }; Reconstructible> _resume_main_handler { _env.ep(), *this, &Kernel::_resume_main }; diff --git a/repos/libports/src/lib/libc/internal/signal.h b/repos/libports/src/lib/libc/internal/signal.h index 3aca363808..691e86b18e 100644 --- a/repos/libports/src/lib/libc/internal/signal.h +++ b/repos/libports/src/lib/libc/internal/signal.h @@ -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_ */ diff --git a/repos/libports/src/lib/libc/signal.cc b/repos/libports/src/lib/libc/signal.cc index 5a84cafe51..dc9af2d443 100644 --- a/repos/libports/src/lib/libc/signal.cc +++ b/repos/libports/src/lib/libc/signal.cc @@ -25,6 +25,7 @@ extern "C" { #include #include #include +#include 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); }