summaryrefslogtreecommitdiff
path: root/Userland/sleep.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-07 21:19:47 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-07 21:19:47 +0100
commit03a8357e84a9a7c478d787c4705dddf70dc99f7d (patch)
tree23407586e5c6c3069f2b1f8c49c9b916e058b425 /Userland/sleep.cpp
parentc8b308910efa1523f24a935e8d1d38ceb316637f (diff)
downloadserenity-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.cpp47
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;
}