mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 03:22:43 +00:00 
			
		
		
		
	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)
This commit is contained in:
		
							parent
							
								
									52d502e11f
								
							
						
					
					
						commit
						153ea704af
					
				
					 13 changed files with 240 additions and 30 deletions
				
			
		|  | @ -218,6 +218,8 @@ Region* MemoryManager::region_from_laddr(Process& process, LinearAddress laddr) | ||||||
|         if (region->contains(laddr)) |         if (region->contains(laddr)) | ||||||
|             return region.ptr(); |             return region.ptr(); | ||||||
|     } |     } | ||||||
|  |     kprintf("%s(%u) Couldn't find region for L%x\n", process.name().characters(), process.pid(), laddr.get()); | ||||||
|  |     process.dumpRegions(); | ||||||
|     ASSERT_NOT_REACHED(); |     ASSERT_NOT_REACHED(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -731,17 +731,18 @@ void Process::sys$exit(int status) | ||||||
|     switchNow(); |     switchNow(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Process::send_signal(int signal, Process* sender) | void Process::terminate_due_to_signal(int signal, Process* sender) | ||||||
| { | { | ||||||
|     ASSERT_INTERRUPTS_DISABLED(); |     ASSERT_INTERRUPTS_DISABLED(); | ||||||
|     bool wasCurrent = current == sender; |     bool wasCurrent = this == current; | ||||||
|  | 
 | ||||||
|     set_state(Exiting); |     set_state(Exiting); | ||||||
|     s_processes->remove(this); |     s_processes->remove(this); | ||||||
| 
 | 
 | ||||||
|     notify_waiters(m_pid, 0, signal); |     notify_waiters(m_pid, 0, signal); | ||||||
| 
 | 
 | ||||||
|     if (wasCurrent) { |     if (wasCurrent) { | ||||||
|         kprintf("Current process committing suicide!\n"); |         kprintf("Current process (%u) committing suicide!\n", pid()); | ||||||
|         if (!scheduleNewProcess()) { |         if (!scheduleNewProcess()) { | ||||||
|             kprintf("Process::send_signal: Failed to schedule a new process :(\n"); |             kprintf("Process::send_signal: Failed to schedule a new process :(\n"); | ||||||
|             HANG; |             HANG; | ||||||
|  | @ -752,6 +753,75 @@ void Process::send_signal(int signal, Process* sender) | ||||||
|         switchNow(); |         switchNow(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Process::send_signal(int signal, Process* sender) | ||||||
|  | { | ||||||
|  |     ASSERT_INTERRUPTS_DISABLED(); | ||||||
|  |     ASSERT(signal < 32); | ||||||
|  | 
 | ||||||
|  |     // FIXME: Handle send_signal to self.
 | ||||||
|  |     ASSERT(this != current); | ||||||
|  | 
 | ||||||
|  |     auto& action = m_signal_action_data[signal]; | ||||||
|  |     // FIXME: Implement SA_SIGINFO signal handlers.
 | ||||||
|  |     ASSERT(!(action.flags & SA_SIGINFO)); | ||||||
|  | 
 | ||||||
|  |     auto handler_laddr = action.handler_or_sigaction; | ||||||
|  |     if (handler_laddr.is_null()) | ||||||
|  |         return terminate_due_to_signal(signal, sender); | ||||||
|  | 
 | ||||||
|  |     word ret_cs = m_tss.cs; | ||||||
|  |     dword ret_eip = m_tss.eip; | ||||||
|  |     dword ret_eflags = m_tss.eflags; | ||||||
|  | 
 | ||||||
|  |     if ((ret_cs & 3) == 0) { | ||||||
|  |         // FIXME: Handle send_signal to process currently in kernel code.
 | ||||||
|  |         ASSERT_NOT_REACHED(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ProcessPagingScope pagingScope(*this); | ||||||
|  |     dword old_esp = m_tss.esp; | ||||||
|  |     push_value_on_stack(ret_eip); | ||||||
|  |     push_value_on_stack(ret_eflags); | ||||||
|  |     push_value_on_stack(m_tss.eax); | ||||||
|  |     push_value_on_stack(m_tss.ecx); | ||||||
|  |     push_value_on_stack(m_tss.edx); | ||||||
|  |     push_value_on_stack(m_tss.ebx); | ||||||
|  |     push_value_on_stack(old_esp); | ||||||
|  |     push_value_on_stack(m_tss.ebp); | ||||||
|  |     push_value_on_stack(m_tss.esi); | ||||||
|  |     push_value_on_stack(m_tss.edi); | ||||||
|  |     m_tss.eax = (dword)signal; | ||||||
|  |     m_tss.cs = 0x1b; | ||||||
|  |     m_tss.eip = handler_laddr.get(); | ||||||
|  | 
 | ||||||
|  |     if (m_return_from_signal_trampoline.is_null()) { | ||||||
|  |         auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "signal_trampoline", true, true); // FIXME: Remap as read-only after setup.
 | ||||||
|  |         m_return_from_signal_trampoline = region->linearAddress; | ||||||
|  |         byte* code_ptr = m_return_from_signal_trampoline.asPtr(); | ||||||
|  |         *code_ptr++ = 0x61; // popa
 | ||||||
|  |         *code_ptr++ = 0x9d; // popf
 | ||||||
|  |         *code_ptr++ = 0xc3; // ret
 | ||||||
|  |         *code_ptr++ = 0x0f; // ud2
 | ||||||
|  |         *code_ptr++ = 0x0b; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     push_value_on_stack(m_return_from_signal_trampoline.get()); | ||||||
|  | 
 | ||||||
|  |     dbgprintf("signal: %s(%u) sent %d to %s(%u)\n", sender->name().characters(), sender->pid(), signal, name().characters(), pid()); | ||||||
|  | 
 | ||||||
|  |     if (sender == this) { | ||||||
|  |         yield(); | ||||||
|  |         ASSERT_NOT_REACHED(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Process::push_value_on_stack(dword value) | ||||||
|  | { | ||||||
|  |     m_tss.esp -= 4; | ||||||
|  |     dword* stack_ptr = (dword*)m_tss.esp; | ||||||
|  |     *stack_ptr = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Process::processDidCrash(Process* crashedProcess) | void Process::processDidCrash(Process* crashedProcess) | ||||||
| { | { | ||||||
|     ASSERT_INTERRUPTS_DISABLED(); |     ASSERT_INTERRUPTS_DISABLED(); | ||||||
|  | @ -1183,12 +1253,6 @@ int Process::sys$isatty(int fd) | ||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Unix::sighandler_t Process::sys$signal(int signum, Unix::sighandler_t handler) |  | ||||||
| { |  | ||||||
|     dbgprintf("sys$signal: %d => L%x\n", signum, handler); |  | ||||||
|     return nullptr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int Process::sys$kill(pid_t pid, int signal) | int Process::sys$kill(pid_t pid, int signal) | ||||||
| { | { | ||||||
|     if (pid == 0) { |     if (pid == 0) { | ||||||
|  | @ -1466,3 +1530,26 @@ int Process::sys$dup2(int old_fd, int new_fd) | ||||||
|     m_file_descriptors[new_fd] = handle; |     m_file_descriptors[new_fd] = handle; | ||||||
|     return new_fd; |     return new_fd; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | Unix::sighandler_t Process::sys$signal(int signum, Unix::sighandler_t handler) | ||||||
|  | { | ||||||
|  |     // FIXME: Fail with -EINVAL if attepmting to catch or ignore SIGKILL or SIGSTOP.
 | ||||||
|  |     if (signum >= 32) | ||||||
|  |         return (Unix::sighandler_t)-EINVAL; | ||||||
|  |     dbgprintf("sys$signal: %d => L%x\n", signum, handler); | ||||||
|  |     return nullptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int Process::sys$sigaction(int signum, const Unix::sigaction* act, Unix::sigaction* old_act) | ||||||
|  | { | ||||||
|  |     // FIXME: Fail with -EINVAL if attepmting to change action for SIGKILL or SIGSTOP.
 | ||||||
|  |     if (signum >= 32) | ||||||
|  |         return -EINVAL; | ||||||
|  |     VALIDATE_USER_READ(act, sizeof(Unix::sigaction)); | ||||||
|  |     InterruptDisabler disabler; // FIXME: This should use a narrower lock.
 | ||||||
|  |     auto& action = m_signal_action_data[signum]; | ||||||
|  |     action.restorer = LinearAddress((dword)act->sa_restorer); | ||||||
|  |     action.flags = act->sa_flags; | ||||||
|  |     action.handler_or_sigaction = LinearAddress((dword)act->sa_sigaction); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -15,6 +15,13 @@ class PageDirectory; | ||||||
| class Region; | class Region; | ||||||
| class Zone; | class Zone; | ||||||
| 
 | 
 | ||||||
|  | struct SignalActionData { | ||||||
|  |     LinearAddress handler_or_sigaction; | ||||||
|  |     dword mask { 0 }; | ||||||
|  |     int flags { 0 }; | ||||||
|  |     LinearAddress restorer; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class Process : public InlineLinkedListNode<Process> { | class Process : public InlineLinkedListNode<Process> { | ||||||
|     friend class InlineLinkedListNode<Process>; |     friend class InlineLinkedListNode<Process>; | ||||||
| public: | public: | ||||||
|  | @ -129,6 +136,7 @@ public: | ||||||
|     int sys$getdtablesize(); |     int sys$getdtablesize(); | ||||||
|     int sys$dup(int oldfd); |     int sys$dup(int oldfd); | ||||||
|     int sys$dup2(int oldfd, int newfd); |     int sys$dup2(int oldfd, int newfd); | ||||||
|  |     int sys$sigaction(int signum, const Unix::sigaction* act, Unix::sigaction* old_act); | ||||||
| 
 | 
 | ||||||
|     static void initialize(); |     static void initialize(); | ||||||
| 
 | 
 | ||||||
|  | @ -162,6 +170,7 @@ public: | ||||||
|     const FileHandle* file_descriptor(size_t i) const { return m_file_descriptors[i].ptr(); } |     const FileHandle* file_descriptor(size_t i) const { return m_file_descriptors[i].ptr(); } | ||||||
| 
 | 
 | ||||||
|     void send_signal(int signal, Process* sender); |     void send_signal(int signal, Process* sender); | ||||||
|  |     void terminate_due_to_signal(int signal, Process* sender); | ||||||
| 
 | 
 | ||||||
|     Process* fork(RegisterDump&); |     Process* fork(RegisterDump&); | ||||||
|     int exec(const String& path, Vector<String>&& arguments, Vector<String>&& environment); |     int exec(const String& path, Vector<String>&& arguments, Vector<String>&& environment); | ||||||
|  | @ -172,7 +181,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     Process(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& cwd = nullptr, RetainPtr<VirtualFileSystem::Node>&& executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr); |     Process(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& cwd = nullptr, RetainPtr<VirtualFileSystem::Node>&& executable = nullptr, TTY* = nullptr, Process* fork_parent = nullptr); | ||||||
| 
 | 
 | ||||||
|     void allocateLDT(); |     void push_value_on_stack(dword); | ||||||
| 
 | 
 | ||||||
|     PageDirectory* m_page_directory { nullptr }; |     PageDirectory* m_page_directory { nullptr }; | ||||||
| 
 | 
 | ||||||
|  | @ -205,6 +214,7 @@ private: | ||||||
|     int m_waiteeStatus { 0 }; |     int m_waiteeStatus { 0 }; | ||||||
|     int m_fdBlockedOnRead { -1 }; |     int m_fdBlockedOnRead { -1 }; | ||||||
|     size_t m_max_open_file_descriptors { 16 }; |     size_t m_max_open_file_descriptors { 16 }; | ||||||
|  |     SignalActionData m_signal_action_data[32]; | ||||||
| 
 | 
 | ||||||
|     RetainPtr<VirtualFileSystem::Node> m_cwd; |     RetainPtr<VirtualFileSystem::Node> m_cwd; | ||||||
|     RetainPtr<VirtualFileSystem::Node> m_executable; |     RetainPtr<VirtualFileSystem::Node> m_executable; | ||||||
|  | @ -221,6 +231,8 @@ private: | ||||||
|     // FIXME: Implement some kind of ASLR?
 |     // FIXME: Implement some kind of ASLR?
 | ||||||
|     LinearAddress m_nextRegion; |     LinearAddress m_nextRegion; | ||||||
| 
 | 
 | ||||||
|  |     LinearAddress m_return_from_signal_trampoline; | ||||||
|  | 
 | ||||||
|     pid_t m_parentPID { 0 }; |     pid_t m_parentPID { 0 }; | ||||||
| 
 | 
 | ||||||
|     static void notify_waiters(pid_t waitee, int exit_status, int signal); |     static void notify_waiters(pid_t waitee, int exit_status, int signal); | ||||||
|  |  | ||||||
|  | @ -146,6 +146,8 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2, | ||||||
|         return current->sys$dup((int)arg1); |         return current->sys$dup((int)arg1); | ||||||
|     case Syscall::Dup2: |     case Syscall::Dup2: | ||||||
|         return current->sys$dup2((int)arg1, (int)arg2); |         return current->sys$dup2((int)arg1, (int)arg2); | ||||||
|  |     case Syscall::Sigaction: | ||||||
|  |         return current->sys$sigaction((int)arg1, (const Unix::sigaction*)arg2, (Unix::sigaction*)arg3); | ||||||
|     default: |     default: | ||||||
|         kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); |         kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ enum Function { | ||||||
|     Getdtablesize = 0x2024, |     Getdtablesize = 0x2024, | ||||||
|     Dup = 0x2025, |     Dup = 0x2025, | ||||||
|     Dup2 = 0x2026, |     Dup2 = 0x2026, | ||||||
|  |     Sigaction = 0x2027, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void initialize(); | void initialize(); | ||||||
|  |  | ||||||
|  | @ -22,5 +22,11 @@ sighandler_t signal(int signum, sighandler_t handler) | ||||||
|     return old_handler; |     return old_handler; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int sigaction(int signum, const struct sigaction* act, struct sigaction* old_act) | ||||||
|  | { | ||||||
|  |     int rc = Syscall::invoke(Syscall::Sigaction, (dword)signum, (dword)act, (dword)old_act); | ||||||
|  |     __RETURN_WITH_ERRNO(rc, rc, -1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,8 +11,10 @@ typedef uint32_t sigset_t; | ||||||
| typedef void siginfo_t; | typedef void siginfo_t; | ||||||
| 
 | 
 | ||||||
| struct sigaction { | struct sigaction { | ||||||
|     void (*sa_handler)(int); |     union { | ||||||
|     void (*sa_sigaction)(int, siginfo_t*, void*); |         void (*sa_handler)(int); | ||||||
|  |         void (*sa_sigaction)(int, siginfo_t*, void*); | ||||||
|  |     }; | ||||||
|     sigset_t sa_mask; |     sigset_t sa_mask; | ||||||
|     int sa_flags; |     int sa_flags; | ||||||
|     void (*sa_restorer)(void); |     void (*sa_restorer)(void); | ||||||
|  | @ -20,11 +22,16 @@ struct sigaction { | ||||||
| 
 | 
 | ||||||
| int kill(pid_t, int sig); | int kill(pid_t, int sig); | ||||||
| sighandler_t signal(int sig, sighandler_t); | sighandler_t signal(int sig, sighandler_t); | ||||||
|  | int sigaction(int signum, const struct sigaction* act, struct sigaction* old_act); | ||||||
| 
 | 
 | ||||||
| #define SIG_DFL ((__sighandler_t)0) | #define SIG_DFL ((__sighandler_t)0) | ||||||
| #define SIG_ERR ((__sighandler_t)-1) | #define SIG_ERR ((__sighandler_t)-1) | ||||||
| #define SIG_IGN ((__sighandler_t)1) | #define SIG_IGN ((__sighandler_t)1) | ||||||
| 
 | 
 | ||||||
|  | #define SA_NOCLDSTOP 1 | ||||||
|  | #define SA_NOCLDWAIT 2 | ||||||
|  | #define SA_SIGINFO 4 | ||||||
|  | 
 | ||||||
| #define SIG_BLOCK 0 | #define SIG_BLOCK 0 | ||||||
| #define SIG_UNBLOCK 1 | #define SIG_UNBLOCK 1 | ||||||
| #define SIG_SETMASK 2 | #define SIG_SETMASK 2 | ||||||
|  |  | ||||||
|  | @ -5,15 +5,15 @@ | ||||||
| 
 | 
 | ||||||
| __BEGIN_DECLS | __BEGIN_DECLS | ||||||
| 
 | 
 | ||||||
| void* malloc(size_t); | void* malloc(size_t) __MALLOC; | ||||||
| void free(void*); | void free(void*); | ||||||
| void* calloc(size_t nmemb, size_t); | void* calloc(size_t nmemb, size_t); | ||||||
| void* realloc(void *ptr, size_t); | void* realloc(void *ptr, size_t); | ||||||
| char* getenv(const char* name); | char* getenv(const char* name); | ||||||
| int atoi(const char*); | int atoi(const char*); | ||||||
| 
 | 
 | ||||||
| void exit(int status); | void exit(int status) __NORETURN; | ||||||
| void abort(); | void abort() __NORETURN; | ||||||
| 
 | 
 | ||||||
| __END_DECLS | __END_DECLS | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #define ALWAYS_INLINE inline __attribute__ ((always_inline)) | #define ALWAYS_INLINE inline __attribute__ ((always_inline)) | ||||||
| #define __NORETURN __attribute__ ((noreturn)) | #define __NORETURN __attribute__ ((noreturn)) | ||||||
|  | #define __MALLOC __attribute__ ((malloc)) | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| #define __BEGIN_DECLS extern "C" { | #define __BEGIN_DECLS extern "C" { | ||||||
|  |  | ||||||
|  | @ -1,7 +1,9 @@ | ||||||
| #include <LibC/stdio.h> | #include <stdio.h> | ||||||
| #include <LibC/unistd.h> | #include <unistd.h> | ||||||
| #include <LibC/errno.h> | #include <errno.h> | ||||||
| #include <LibC/string.h> | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <assert.h> | ||||||
| 
 | 
 | ||||||
| int main(int argc, char** argv) | int main(int argc, char** argv) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <LibC/unistd.h> | #include <unistd.h> | ||||||
| #include <LibC/stdio.h> | #include <stdio.h> | ||||||
| #include <LibC/signal.h> | #include <signal.h> | ||||||
|  | #include <stdlib.h> | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
| 
 | 
 | ||||||
| static unsigned parseUInt(const String& str, bool& ok) | static unsigned parseUInt(const String& str, bool& ok) | ||||||
|  | @ -18,20 +19,36 @@ static unsigned parseUInt(const String& str, bool& ok) | ||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void print_usage_and_exit() | ||||||
|  | { | ||||||
|  |     printf("usage: kill [-signal] <PID>\n"); | ||||||
|  |     exit(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int main(int argc, char** argv) | int main(int argc, char** argv) | ||||||
| { | { | ||||||
|     if (argc < 2) { |     if (argc != 2 && argc != 3) | ||||||
|         printf("usage: kill <PID>\n"); |         print_usage_and_exit(); | ||||||
|         return 1; |  | ||||||
|     } |  | ||||||
|     bool ok; |     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) { |     if (!ok) { | ||||||
|         printf("%s is not a valid PID\n", argv[1]); |         printf("%s is not a valid PID\n", argv[pid_argi]); | ||||||
|         return 2; |         return 3; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     kill((pid_t)value, SIGKILL); |     kill((pid_t)pid, signum); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include <LibC/stdlib.h> | #include <LibC/stdlib.h> | ||||||
| #include <LibC/utsname.h> | #include <LibC/utsname.h> | ||||||
| #include <LibC/pwd.h> | #include <LibC/pwd.h> | ||||||
|  | #include <signal.h> | ||||||
| #include <AK/FileSystemPath.h> | #include <AK/FileSystemPath.h> | ||||||
| 
 | 
 | ||||||
| struct GlobalState { | struct GlobalState { | ||||||
|  | @ -32,6 +33,29 @@ static int sh_pwd(int, const char**) | ||||||
|     return 0; |     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**) | static int sh_fork(int, const char**) | ||||||
| { | { | ||||||
|     pid_t pid = fork(); |     pid_t pid = fork(); | ||||||
|  | @ -147,6 +171,10 @@ static bool handle_builtin(int argc, const char** argv, int& retval) | ||||||
|         retval = sh_fef(argc, argv); |         retval = sh_fef(argc, argv); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |     if (!strcmp(argv[0], "busy")) { | ||||||
|  |         retval = sh_busy(argc, argv); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|     if (!strcmp(argv[0], "wt")) { |     if (!strcmp(argv[0], "wt")) { | ||||||
|         retval = sh_wt(argc, argv); |         retval = sh_wt(argc, argv); | ||||||
|         return true; |         return true; | ||||||
|  |  | ||||||
|  | @ -20,9 +20,54 @@ typedef dword nlink_t; | ||||||
| typedef dword uid_t; | typedef dword uid_t; | ||||||
| typedef dword gid_t; | typedef dword gid_t; | ||||||
| 
 | 
 | ||||||
|  | #ifdef SERENITY | ||||||
| typedef void (*__sighandler_t)(int); | typedef void (*__sighandler_t)(int); | ||||||
| typedef __sighandler_t sighandler_t; | typedef __sighandler_t sighandler_t; | ||||||
| 
 | 
 | ||||||
|  | typedef dword sigset_t; | ||||||
|  | typedef void siginfo_t; | ||||||
|  | 
 | ||||||
|  | struct sigaction { | ||||||
|  |     union { | ||||||
|  |         void (*sa_handler)(int); | ||||||
|  |         void (*sa_sigaction)(int, siginfo_t*, void*); | ||||||
|  |     }; | ||||||
|  |     sigset_t sa_mask; | ||||||
|  |     int sa_flags; | ||||||
|  |     void (*sa_restorer)(void); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define SA_NOCLDSTOP 1 | ||||||
|  | #define SA_NOCLDWAIT 2 | ||||||
|  | #define SA_SIGINFO 4 | ||||||
|  | 
 | ||||||
|  | #define SIG_BLOCK 0 | ||||||
|  | #define SIG_UNBLOCK 1 | ||||||
|  | #define SIG_SETMASK 2 | ||||||
|  | 
 | ||||||
|  | #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 | ||||||
|  | #define SIGCONT  18 | ||||||
|  | #define SIGTSTP  20 | ||||||
|  | #define SIGTTIN  21 | ||||||
|  | #define SIGTTOU  22 | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #ifdef SERENITY | #ifdef SERENITY | ||||||
| // FIXME: Support 64-bit offsets!
 | // FIXME: Support 64-bit offsets!
 | ||||||
| typedef signed_dword off_t; | typedef signed_dword off_t; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling