summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-06 10:46:40 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-06 10:56:41 +0100
commit153ea704af5e22c70e169f112e9df3e4cd9a6f11 (patch)
treee879dcf3decc9e162d3a4f0a746b05214b7899c1 /Userland
parent52d502e11f3207f2c5c36e7cc676f43f249fc351 (diff)
downloadserenity-153ea704af5e22c70e169f112e9df3e4cd9a6f11.zip
Add some basic signal support.
It only works for sending a signal to a process that's in userspace code. We implement reception by synthesizing a PUSHA+PUSHF in the receiving process (operating on values in the TSS.) The TSS CS:EIP is then rerouted to the signal handler and a tiny return trampoline is constructed in a dedicated region in the receiving process. Also hacked up /bin/kill to be able to send arbitrary signals (kill -N PID)
Diffstat (limited to 'Userland')
-rw-r--r--Userland/cat.cpp10
-rw-r--r--Userland/kill.cpp39
-rw-r--r--Userland/sh.cpp28
3 files changed, 62 insertions, 15 deletions
diff --git a/Userland/cat.cpp b/Userland/cat.cpp
index b127bf2cc9..ab003a2a7d 100644
--- a/Userland/cat.cpp
+++ b/Userland/cat.cpp
@@ -1,7 +1,9 @@
-#include <LibC/stdio.h>
-#include <LibC/unistd.h>
-#include <LibC/errno.h>
-#include <LibC/string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
int main(int argc, char** argv)
{
diff --git a/Userland/kill.cpp b/Userland/kill.cpp
index 573b58fe4c..10cc9c1b62 100644
--- a/Userland/kill.cpp
+++ b/Userland/kill.cpp
@@ -1,6 +1,7 @@
-#include <LibC/unistd.h>
-#include <LibC/stdio.h>
-#include <LibC/signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
#include <AK/String.h>
static unsigned parseUInt(const String& str, bool& ok)
@@ -18,20 +19,36 @@ static unsigned parseUInt(const String& str, bool& ok)
return value;
}
+static void print_usage_and_exit()
+{
+ printf("usage: kill [-signal] <PID>\n");
+ exit(1);
+}
+
int main(int argc, char** argv)
{
- if (argc < 2) {
- printf("usage: kill <PID>\n");
- return 1;
- }
+ if (argc != 2 && argc != 3)
+ print_usage_and_exit();
bool ok;
- unsigned value = parseUInt(argv[1], ok);
+ unsigned signum = SIGTERM;
+ int pid_argi = 1;
+ if (argc == 3) {
+ pid_argi = 2;
+ if (argv[1][0] != '-')
+ print_usage_and_exit();
+ signum = parseUInt(&argv[1][1], ok);
+ if (!ok) {
+ printf("%s is not a valid signal number\n", &argv[1][1]);
+ return 2;
+ }
+ }
+ unsigned pid = parseUInt(argv[pid_argi], ok);
if (!ok) {
- printf("%s is not a valid PID\n", argv[1]);
- return 2;
+ printf("%s is not a valid PID\n", argv[pid_argi]);
+ return 3;
}
- kill((pid_t)value, SIGKILL);
+ kill((pid_t)pid, signum);
return 0;
}
diff --git a/Userland/sh.cpp b/Userland/sh.cpp
index 1ec61c2ed4..5d8c224b9a 100644
--- a/Userland/sh.cpp
+++ b/Userland/sh.cpp
@@ -6,6 +6,7 @@
#include <LibC/stdlib.h>
#include <LibC/utsname.h>
#include <LibC/pwd.h>
+#include <signal.h>
#include <AK/FileSystemPath.h>
struct GlobalState {
@@ -32,6 +33,29 @@ static int sh_pwd(int, const char**)
return 0;
}
+void did_receive_signal(int signum)
+{
+ printf("\nMy word, I've received a signal with number %d\n", signum);
+ //exit(0);
+}
+
+static int sh_busy(int, const char**)
+{
+ struct sigaction sa;
+ sa.sa_handler = did_receive_signal;
+ sa.sa_flags = 0;
+ sa.sa_mask = 0;
+ sa.sa_restorer = nullptr;
+ int rc = sigaction(SIGUSR1, &sa, nullptr);
+ assert(rc == 0);
+ printf("listening for SIGUSR1 while looping in userspace...\n");
+ for (;;) {
+ for (volatile int i = 0; i < 100000; ++i)
+ ;
+ }
+ return 0;
+}
+
static int sh_fork(int, const char**)
{
pid_t pid = fork();
@@ -147,6 +171,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval)
retval = sh_fef(argc, argv);
return true;
}
+ if (!strcmp(argv[0], "busy")) {
+ retval = sh_busy(argc, argv);
+ return true;
+ }
if (!strcmp(argv[0], "wt")) {
retval = sh_wt(argc, argv);
return true;