diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-11-07 21:19:47 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-11-07 21:19:47 +0100 |
commit | 03a8357e84a9a7c478d787c4705dddf70dc99f7d (patch) | |
tree | 23407586e5c6c3069f2b1f8c49c9b916e058b425 /Userland/sleep.cpp | |
parent | c8b308910efa1523f24a935e8d1d38ceb316637f (diff) | |
download | serenity-03a8357e84a9a7c478d787c4705dddf70dc99f7d.zip |
Implement sending signals to blocked-in-kernel processes.
This is dirty but pretty cool! If we have a pending, unmasked signal for
a process that's blocked inside the kernel, we set up alternate stacks
for that process and unblock it to execute the signal handler.
A slightly different return trampoline is used here: since we need to
get back into the kernel, a dedicated syscall is used (sys$sigreturn.)
This restores the TSS contents of the process to the state it was in
while we were originally blocking in the kernel.
NOTE: There's currently only one "kernel resume TSS" so signal nesting
definitely won't work.
Diffstat (limited to 'Userland/sleep.cpp')
-rw-r--r-- | Userland/sleep.cpp | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/Userland/sleep.cpp b/Userland/sleep.cpp index c0e7c44eea..79cffbfc1b 100644 --- a/Userland/sleep.cpp +++ b/Userland/sleep.cpp @@ -1,10 +1,47 @@ -#include <LibC/unistd.h> -#include <LibC/stdio.h> +#include <unistd.h> +#include <stdio.h> +#include <signal.h> +#include <AK/String.h> -int main(int c, char** v) +static unsigned parseUInt(const String& str, bool& ok) { - unsigned secs = 10; - sleep(secs); + unsigned value = 0; + for (size_t i = 0; i < str.length(); ++i) { + if (str[i] < '0' || str[i] > '9') { + ok = false; + return 0; + } + value = value * 10; + value += str[i] - '0'; + } + ok = true; + return value; +} + +void handle_sigint(int) +{ +} + +int main(int argc, char** argv) +{ + if (argc != 2) { + printf("usage: sleep <seconds>\n"); + return 1; + } + bool ok; + unsigned secs = parseUInt(argv[1], ok); + if (!ok) { + fprintf(stderr, "Not a valid number of seconds: \"%s\"\n", argv[1]); + return 1; + } + struct sigaction sa; + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = handle_sigint; + sigaction(SIGINT, &sa, nullptr); + unsigned remaining = sleep(secs); + if (remaining) { + printf("Sleep interrupted with %u seconds remaining.\n", remaining); + } return 0; } |