diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 8b4a4a7f6f..ba2021c9a2 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -80,7 +80,6 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) kprintf("syscall: seek(%d, %d)\n", arg1, arg2); return current->sys$seek((int)arg1, (int)arg2); case Syscall::PosixKill: - kprintf("syscall: kill(%d, %d)\n", arg1, arg2); return current->sys$kill((pid_t)arg1, (int)arg2); case Syscall::PosixGetuid: return current->sys$getuid(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 5d71342500..0512289cfe 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -513,6 +513,24 @@ void Task::sys$exit(int status) switchNow(); } +void Task::murder() +{ + ASSERT_INTERRUPTS_DISABLED(); + bool wasCurrent = current == this; + setState(Exiting); + s_tasks->remove(this); + if (wasCurrent) { + MM.unmapRegionsForTask(*this); + if (!scheduleNewTask()) { + kprintf("Task::murder: Failed to schedule a new task :(\n"); + HANG; + } + } + s_deadTasks->append(this); + if (wasCurrent) + switchNow(); +} + void Task::taskDidCrash(Task* crashedTask) { ASSERT_INTERRUPTS_DISABLED(); @@ -749,7 +767,7 @@ int Task::sys$seek(int fd, int offset) { auto* handle = fileHandleIfExists(fd); if (!handle) - return -EBADF; + return -1; return handle->seek(offset, SEEK_SET); } @@ -924,11 +942,15 @@ int Task::sys$kill(pid_t pid, int sig) // FIXME: Send to all processes. ASSERT(pid != -1); } - ASSERT_NOT_REACHED(); - Task* peer = Task::fromPID(pid); - if (!peer) { - // errno = ESRCH; - return -1; + ASSERT(pid != current->pid()); // FIXME: Support this scenario. + InterruptDisabler disabler; + auto* peer = Task::fromPID(pid); + if (!peer) + return -ESRCH; + if (sig == 9) { + peer->murder(); + } else { + ASSERT_NOT_REACHED(); } return -1; } diff --git a/Kernel/Task.h b/Kernel/Task.h index 15536385b9..60d7d74767 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -216,6 +216,8 @@ private: pid_t m_parentPID { 0 }; + void murder(); + Vector m_arguments; }; diff --git a/Kernel/sync-sh b/Kernel/sync-sh index 4847c68a40..d455f52f31 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -16,6 +16,7 @@ cp ../Userland/uname mnt/bin/uname cp ../Userland/clear mnt/bin/clear cp ../Userland/tst mnt/bin/tst cp ../Userland/mm mnt/bin/mm +cp ../Userland/kill mnt/bin/kill cp kernel.map mnt/ umount mnt sync diff --git a/LibC/Makefile b/LibC/Makefile index c376122965..15f5b33b7a 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -16,6 +16,7 @@ LIBC_OBJS = \ time.o \ utsname.o \ assert.o \ + signal.o \ entry.o OBJS = $(AK_OBJS) $(LIBC_OBJS) diff --git a/LibC/signal.cpp b/LibC/signal.cpp new file mode 100644 index 0000000000..ab73f4a5e8 --- /dev/null +++ b/LibC/signal.cpp @@ -0,0 +1,14 @@ +#include "unistd.h" +#include "errno.h" +#include + +extern "C" { + +int kill(pid_t pid, int sig) +{ + int rc = Syscall::invoke(Syscall::PosixKill, (dword)pid, (dword)sig); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +} + diff --git a/LibC/signal.h b/LibC/signal.h new file mode 100644 index 0000000000..6a138098b6 --- /dev/null +++ b/LibC/signal.h @@ -0,0 +1,26 @@ +#pragma once + +#include "types.h" + +extern "C" { + +int kill(pid_t, int sig); + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 + +} + diff --git a/Userland/.gitignore b/Userland/.gitignore index f6b0db7615..7207e83cfc 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -14,3 +14,4 @@ uname clear tst mm +kill diff --git a/Userland/Makefile b/Userland/Makefile index bc8e0ecaee..08ee253c74 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -13,7 +13,8 @@ OBJS = \ uname.o \ clear.o \ tst.o \ - mm.o + mm.o \ + kill.o APPS = \ id \ @@ -30,7 +31,8 @@ APPS = \ uname \ clear \ tst \ - mm + mm \ + kill ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -95,6 +97,9 @@ tst: tst.o mm: mm.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +kill: kill.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/kill.cpp b/Userland/kill.cpp new file mode 100644 index 0000000000..573b58fe4c --- /dev/null +++ b/Userland/kill.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +static unsigned parseUInt(const String& str, bool& ok) +{ + 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; +} + +int main(int argc, char** argv) +{ + if (argc < 2) { + printf("usage: kill \n"); + return 1; + } + bool ok; + unsigned value = parseUInt(argv[1], ok); + if (!ok) { + printf("%s is not a valid PID\n", argv[1]); + return 2; + } + + kill((pid_t)value, SIGKILL); + return 0; +} +