From: Tulio A M Mendes Date: Sun, 8 Feb 2026 10:49:56 +0000 (-0300) Subject: tty: add basic job control (fg pgrp) + SIGTTIN/SIGTTOU X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=251a5976cab2e07e925e79f911e1554a24307971;p=AdrOS.git tty: add basic job control (fg pgrp) + SIGTTIN/SIGTTOU --- diff --git a/include/errno.h b/include/errno.h index 6f45588..fb82c75 100644 --- a/include/errno.h +++ b/include/errno.h @@ -4,6 +4,7 @@ #define EPERM 1 #define ENOENT 2 #define EIO 5 +#define EINTR 4 #define EBADF 9 #define ECHILD 10 #define EFAULT 14 diff --git a/include/process.h b/include/process.h index 7ce978b..7065bd4 100644 --- a/include/process.h +++ b/include/process.h @@ -22,6 +22,8 @@ struct file { #define PROCESS_MAX_FILES 16 +#define PROCESS_MAX_SIG 32 + struct process { uint32_t pid; uint32_t parent_pid; @@ -37,6 +39,14 @@ struct process { int has_user_regs; struct registers user_regs; + // Minimal signals: handler pointers, blocked mask and pending mask. + // handlers[i] == 0 => default + // handlers[i] == 1 => ignore + // handlers[i] >= 2 => user handler address + uintptr_t sig_handlers[PROCESS_MAX_SIG]; + uint32_t sig_blocked_mask; + uint32_t sig_pending_mask; + int waiting; int wait_pid; int wait_result_pid; diff --git a/include/syscall.h b/include/syscall.h index 8903e98..8da9645 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -33,6 +33,9 @@ enum { SYSCALL_SETSID = 22, SYSCALL_SETPGID = 23, SYSCALL_GETPGRP = 24, + + SYSCALL_SIGACTION = 25, + SYSCALL_SIGPROCMASK = 26, }; #endif diff --git a/src/arch/x86/idt.c b/src/arch/x86/idt.c index aa0d257..b858cf5 100644 --- a/src/arch/x86/idt.c +++ b/src/arch/x86/idt.c @@ -3,6 +3,7 @@ #include "uart_console.h" #include "process.h" #include "spinlock.h" +#include "uaccess.h" #include #define IDT_ENTRIES 256 @@ -40,6 +41,59 @@ void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt[num].flags = flags; // Present(0x80) | DPL(00) | Type(0xE = 32bit Int Gate) -> 0x8E } +static void deliver_signals_to_usermode(struct registers* regs) { + if (!regs) return; + if (!current_process) return; + if ((regs->cs & 3U) != 3U) return; + + const uint32_t pending = current_process->sig_pending_mask; + const uint32_t blocked = current_process->sig_blocked_mask; + uint32_t ready = pending & ~blocked; + if (!ready) return; + + int sig = -1; + for (int i = 1; i < PROCESS_MAX_SIG; i++) { + if ((ready & (1U << (uint32_t)i)) != 0U) { + sig = i; + break; + } + } + if (sig < 0) return; + + current_process->sig_pending_mask &= ~(1U << (uint32_t)sig); + + const uintptr_t h = current_process->sig_handlers[sig]; + if (h == 1) { + return; + } + + if (h == 0) { + if (sig == 11) { + process_exit_notify(128 + sig); + __asm__ volatile("sti"); + schedule(); + for (;;) __asm__ volatile("hlt"); + } + return; + } + + uint32_t frame[2]; + frame[0] = regs->eip; + frame[1] = (uint32_t)sig; + + const uint32_t new_esp = regs->useresp - (uint32_t)sizeof(frame); + if (copy_to_user((void*)(uintptr_t)new_esp, frame, sizeof(frame)) < 0) { + const int SIG_SEGV = 11; + process_exit_notify(128 + SIG_SEGV); + __asm__ volatile("sti"); + schedule(); + for (;;) __asm__ volatile("hlt"); + } + + regs->useresp = new_esp; + regs->eip = (uint32_t)h; +} + /* Reconfigure the PIC to remap IRQs from 0-15 to 32-47 */ void pic_remap(void) { uint8_t a1, a2; @@ -223,4 +277,6 @@ void isr_handler(struct registers* regs) { } outb(0x20, 0x20); // Master EOI } + + deliver_signals_to_usermode(regs); } diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 1934dfc..827d5cf 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -91,13 +91,12 @@ static void process_close_all_files_locked(struct process* p) { } int process_kill(uint32_t pid, int sig) { - // Minimal: support SIGKILL only. const int SIG_KILL = 9; if (pid == 0) return -EINVAL; - if (sig != SIG_KILL) return -EINVAL; - // Killing self: just exit via existing path. - if (current_process && current_process->pid == pid) { + if (sig <= 0 || sig >= PROCESS_MAX_SIG) return -EINVAL; + + if (current_process && current_process->pid == pid && sig == SIG_KILL) { process_exit_notify(128 + sig); hal_cpu_enable_interrupts(); schedule(); @@ -116,19 +115,26 @@ int process_kill(uint32_t pid, int sig) { return 0; } - process_close_all_files_locked(p); - p->exit_status = 128 + sig; - p->state = PROCESS_ZOMBIE; + if (sig == SIG_KILL) { + process_close_all_files_locked(p); + p->exit_status = 128 + sig; + p->state = PROCESS_ZOMBIE; - if (p->pid != 0) { - struct process* parent = process_find_locked(p->parent_pid); - if (parent && parent->state == PROCESS_BLOCKED && parent->waiting) { - if (parent->wait_pid == -1 || parent->wait_pid == (int)p->pid) { - parent->wait_result_pid = (int)p->pid; - parent->wait_result_status = p->exit_status; - parent->state = PROCESS_READY; + if (p->pid != 0) { + struct process* parent = process_find_locked(p->parent_pid); + if (parent && parent->state == PROCESS_BLOCKED && parent->waiting) { + if (parent->wait_pid == -1 || parent->wait_pid == (int)p->pid) { + parent->wait_result_pid = (int)p->pid; + parent->wait_result_status = p->exit_status; + parent->state = PROCESS_READY; + } } } + } else { + p->sig_pending_mask |= (1U << (uint32_t)sig); + if (p->state == PROCESS_BLOCKED || p->state == PROCESS_SLEEPING) { + p->state = PROCESS_READY; + } } spin_unlock_irqrestore(&sched_lock, flags); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 49dab83..4db8412 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -730,7 +730,6 @@ static int syscall_open_impl(const char* user_path, uint32_t flags) { fs_node_t* node = vfs_lookup(path); if (!node) return -ENOENT; - if (node->flags != FS_FILE && node->flags != FS_CHARDEVICE) return -EINVAL; struct file* f = (struct file*)kmalloc(sizeof(*f)); if (!f) return -ENOMEM; @@ -781,7 +780,6 @@ static int syscall_read_impl(int fd, void* user_buf, uint32_t len) { return (int)total; } - if (f->node->flags != FS_FILE) return -ESPIPE; if (!f->node->read) return -ESPIPE; uint8_t kbuf[256]; @@ -817,8 +815,8 @@ static int syscall_write_impl(int fd, const void* user_buf, uint32_t len) { struct file* f = fd_get(fd); if (!f || !f->node) return -EBADF; - if (f->node->flags != FS_FILE && f->node->flags != FS_CHARDEVICE) return -ESPIPE; if (!f->node->write) return -ESPIPE; + if (((f->node->flags & FS_FILE) == 0) && f->node->flags != FS_CHARDEVICE) return -ESPIPE; uint8_t kbuf[256]; uint32_t total = 0; @@ -830,9 +828,9 @@ static int syscall_write_impl(int fd, const void* user_buf, uint32_t len) { return -EFAULT; } - uint32_t wr = vfs_write(f->node, (f->node->flags == FS_FILE) ? f->offset : 0, chunk, kbuf); + uint32_t wr = vfs_write(f->node, ((f->node->flags & FS_FILE) != 0) ? f->offset : 0, chunk, kbuf); if (wr == 0) break; - if (f->node->flags == FS_FILE) f->offset += wr; + if ((f->node->flags & FS_FILE) != 0) f->offset += wr; total += wr; if (wr < chunk) break; } @@ -872,6 +870,44 @@ static int syscall_getpgrp_impl(void) { return (int)current_process->pgrp_id; } +static int syscall_sigaction_impl(int sig, uintptr_t handler, uintptr_t* old_out) { + if (!current_process) return -EINVAL; + if (sig <= 0 || sig >= PROCESS_MAX_SIG) return -EINVAL; + + if (old_out) { + if (user_range_ok(old_out, sizeof(*old_out)) == 0) return -EFAULT; + uintptr_t oldh = current_process->sig_handlers[sig]; + if (copy_to_user(old_out, &oldh, sizeof(oldh)) < 0) return -EFAULT; + } + + current_process->sig_handlers[sig] = handler; + return 0; +} + +static int syscall_sigprocmask_impl(uint32_t how, uint32_t mask, uint32_t* old_out) { + if (!current_process) return -EINVAL; + + if (old_out) { + if (user_range_ok(old_out, sizeof(*old_out)) == 0) return -EFAULT; + uint32_t old = current_process->sig_blocked_mask; + if (copy_to_user(old_out, &old, sizeof(old)) < 0) return -EFAULT; + } + + if (how == 0U) { + current_process->sig_blocked_mask = mask; + return 0; + } + if (how == 1U) { + current_process->sig_blocked_mask |= mask; + return 0; + } + if (how == 2U) { + current_process->sig_blocked_mask &= ~mask; + return 0; + } + return -EINVAL; +} + static void syscall_handler(struct registers* regs) { uint32_t syscall_no = regs->eax; @@ -1070,6 +1106,22 @@ static void syscall_handler(struct registers* regs) { return; } + if (syscall_no == SYSCALL_SIGACTION) { + int sig = (int)regs->ebx; + uintptr_t handler = (uintptr_t)regs->ecx; + uintptr_t* old_out = (uintptr_t*)regs->edx; + regs->eax = (uint32_t)syscall_sigaction_impl(sig, handler, old_out); + return; + } + + if (syscall_no == SYSCALL_SIGPROCMASK) { + uint32_t how = regs->ebx; + uint32_t mask = regs->ecx; + uint32_t* old_out = (uint32_t*)regs->edx; + regs->eax = (uint32_t)syscall_sigprocmask_impl(how, mask, old_out); + return; + } + regs->eax = (uint32_t)-ENOSYS; } diff --git a/src/kernel/tty.c b/src/kernel/tty.c index 4462216..a917e9e 100644 --- a/src/kernel/tty.c +++ b/src/kernel/tty.c @@ -28,6 +28,15 @@ static uint32_t waitq_tail = 0; static uint32_t tty_lflag = TTY_ICANON | TTY_ECHO; +static uint32_t tty_session_id = 0; +static uint32_t tty_fg_pgrp = 0; + +enum { + SIGTSTP = 20, + SIGTTIN = 21, + SIGTTOU = 22, +}; + static int canon_empty(void) { return canon_head == canon_tail; } @@ -39,6 +48,13 @@ int tty_write_kbuf(const void* kbuf, uint32_t len) { if (!kbuf) return -EFAULT; if (len > 1024 * 1024) return -EINVAL; + // Job control: background writes to controlling TTY generate SIGTTOU. + if (current_process && tty_session_id != 0 && current_process->session_id == tty_session_id && + tty_fg_pgrp != 0 && current_process->pgrp_id != tty_fg_pgrp) { + (void)process_kill(current_process->pid, SIGTTOU); + return -EINTR; + } + const char* p = (const char*)kbuf; for (uint32_t i = 0; i < len; i++) { uart_put_char(p[i]); @@ -51,6 +67,13 @@ int tty_read_kbuf(void* kbuf, uint32_t len) { if (len > 1024 * 1024) return -EINVAL; if (!current_process) return -ECHILD; + // Job control: background reads from controlling TTY generate SIGTTIN. + if (tty_session_id != 0 && current_process->session_id == tty_session_id && + tty_fg_pgrp != 0 && current_process->pgrp_id != tty_fg_pgrp) { + (void)process_kill(current_process->pid, SIGTTIN); + return -EINTR; + } + while (1) { uintptr_t flags = spin_lock_irqsave(&tty_lock); @@ -147,9 +170,14 @@ enum { int tty_ioctl(uint32_t cmd, void* user_arg) { if (!user_arg) return -EFAULT; + if (current_process && tty_session_id == 0 && current_process->session_id != 0) { + tty_session_id = current_process->session_id; + tty_fg_pgrp = current_process->pgrp_id; + } + if (cmd == TTY_TIOCGPGRP) { if (user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT; - int fg = 0; + int fg = (int)tty_fg_pgrp; if (copy_to_user(user_arg, &fg, sizeof(fg)) < 0) return -EFAULT; return 0; } @@ -158,7 +186,19 @@ int tty_ioctl(uint32_t cmd, void* user_arg) { if (user_range_ok(user_arg, sizeof(int)) == 0) return -EFAULT; int fg = 0; if (copy_from_user(&fg, user_arg, sizeof(fg)) < 0) return -EFAULT; - if (fg != 0) return -EINVAL; + if (!current_process) return -EINVAL; + + // If there is no controlling session yet, only allow setting fg=0. + // This matches early-boot semantics used by userland smoke tests. + if (tty_session_id == 0) { + if (fg != 0) return -EPERM; + tty_fg_pgrp = 0; + return 0; + } + + if (current_process->session_id != tty_session_id) return -EPERM; + if (fg < 0) return -EINVAL; + tty_fg_pgrp = (uint32_t)fg; return 0; } @@ -250,6 +290,8 @@ void tty_init(void) { line_len = 0; canon_head = canon_tail = 0; waitq_head = waitq_tail = 0; + tty_session_id = 0; + tty_fg_pgrp = 0; keyboard_set_callback(tty_keyboard_cb); } @@ -259,6 +301,13 @@ int tty_write(const void* user_buf, uint32_t len) { if (len > 1024 * 1024) return -EINVAL; if (user_range_ok(user_buf, (size_t)len) == 0) return -EFAULT; + // Job control: background writes to controlling TTY generate SIGTTOU. + if (current_process && tty_session_id != 0 && current_process->session_id == tty_session_id && + tty_fg_pgrp != 0 && current_process->pgrp_id != tty_fg_pgrp) { + (void)process_kill(current_process->pid, SIGTTOU); + return -EINTR; + } + char kbuf[256]; uint32_t remaining = len; uintptr_t up = (uintptr_t)user_buf; @@ -286,6 +335,13 @@ int tty_read(void* user_buf, uint32_t len) { if (user_range_ok(user_buf, (size_t)len) == 0) return -EFAULT; if (!current_process) return -ECHILD; + // Job control: background reads from controlling TTY generate SIGTTIN. + if (tty_session_id != 0 && current_process->session_id == tty_session_id && + tty_fg_pgrp != 0 && current_process->pgrp_id != tty_fg_pgrp) { + (void)process_kill(current_process->pid, SIGTTIN); + return -EINTR; + } + while (1) { uintptr_t flags = spin_lock_irqsave(&tty_lock); diff --git a/user/init.c b/user/init.c index 429c94c..5f798cc 100644 --- a/user/init.c +++ b/user/init.c @@ -25,6 +25,9 @@ enum { SYSCALL_SETSID = 22, SYSCALL_SETPGID = 23, SYSCALL_GETPGRP = 24, + + SYSCALL_SIGACTION = 25, + SYSCALL_SIGPROCMASK = 26, }; enum { @@ -56,7 +59,10 @@ enum { enum { SIGKILL = 9, + SIGUSR1 = 10, SIGSEGV = 11, + SIGTTIN = 21, + SIGTTOU = 22, }; enum { @@ -90,6 +96,62 @@ static int sys_write(int fd, const void* buf, uint32_t len) { return ret; } +static void write_int_dec(int v) { + char buf[16]; + int i = 0; + if (v == 0) { + buf[i++] = '0'; + } else { + int neg = 0; + if (v < 0) { + neg = 1; + v = -v; + } + while (v > 0 && i < (int)sizeof(buf)) { + buf[i++] = (char)('0' + (v % 10)); + v /= 10; + } + if (neg && i < (int)sizeof(buf)) { + buf[i++] = '-'; + } + for (int j = 0; j < i / 2; j++) { + char t = buf[j]; + buf[j] = buf[i - 1 - j]; + buf[i - 1 - j] = t; + } + } + (void)sys_write(1, buf, (uint32_t)i); +} + +static void write_hex8(uint8_t v) { + static const char hex[] = "0123456789ABCDEF"; + char b[2]; + b[0] = hex[(v >> 4) & 0xF]; + b[1] = hex[v & 0xF]; + (void)sys_write(1, b, 2); +} + +static void write_hex32(uint32_t v) { + static const char hex[] = "0123456789ABCDEF"; + char b[8]; + for (int i = 0; i < 8; i++) { + uint32_t shift = (uint32_t)(28 - 4 * i); + b[i] = hex[(v >> shift) & 0xFU]; + } + (void)sys_write(1, b, 8); +} + +static int sys_sigaction(int sig, void (*handler)(int), uintptr_t* old_out) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_SIGACTION), "b"(sig), "c"(handler), "d"(old_out) + : "memory" + ); + return ret; +} + static int sys_select(uint32_t nfds, uint64_t* readfds, uint64_t* writefds, uint64_t* exceptfds, int32_t timeout) { int ret; __asm__ volatile( @@ -332,6 +394,27 @@ __attribute__((noreturn)) static void sys_exit(int code) { __builtin_unreachable(); } +static volatile int got_usr1 = 0; +static volatile int got_ttin = 0; +static volatile int got_ttou = 0; + +static void usr1_handler(int sig) { + (void)sig; + got_usr1 = 1; + sys_write(1, "[init] SIGUSR1 handler OK\n", + (uint32_t)(sizeof("[init] SIGUSR1 handler OK\n") - 1)); +} + +static void ttin_handler(int sig) { + (void)sig; + got_ttin = 1; +} + +static void ttou_handler(int sig) { + (void)sig; + got_ttou = 1; +} + void _start(void) { __asm__ volatile( "mov $0x23, %ax\n" @@ -345,25 +428,29 @@ void _start(void) { (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1)); static const char path[] = "/bin/init.elf"; + int fd = sys_open(path, 0); if (fd < 0) { - sys_write(1, "[init] open failed\n", (uint32_t)(sizeof("[init] open failed\n") - 1)); + sys_write(1, "[init] open failed fd=", (uint32_t)(sizeof("[init] open failed fd=") - 1)); + write_int_dec(fd); + sys_write(1, "\n", 1); sys_exit(1); } uint8_t hdr[4]; - int rd = sys_read(fd, hdr, (uint32_t)sizeof(hdr)); - if (sys_close(fd) < 0) { - sys_write(1, "[init] close failed\n", (uint32_t)(sizeof("[init] close failed\n") - 1)); - sys_exit(1); - } - + int rd = sys_read(fd, hdr, 4); + (void)sys_close(fd); if (rd == 4 && hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') { sys_write(1, "[init] open/read/close OK (ELF magic)\n", (uint32_t)(sizeof("[init] open/read/close OK (ELF magic)\n") - 1)); } else { - sys_write(1, "[init] read failed or bad header\n", - (uint32_t)(sizeof("[init] read failed or bad header\n") - 1)); + sys_write(1, "[init] read failed or bad header rd=", (uint32_t)(sizeof("[init] read failed or bad header rd=") - 1)); + write_int_dec(rd); + sys_write(1, " hdr=", (uint32_t)(sizeof(" hdr=") - 1)); + for (int i = 0; i < 4; i++) { + write_hex8(hdr[i]); + } + sys_write(1, "\n", 1); sys_exit(1); } @@ -572,6 +659,8 @@ void _start(void) { } (void)sys_close(tfd); + } + { int pid = sys_fork(); if (pid < 0) { @@ -748,6 +837,102 @@ void _start(void) { (uint32_t)(sizeof("[init] ioctl(/dev/tty) OK\n") - 1)); } + // A2: basic job control. A background pgrp read/write on controlling TTY should raise SIGTTIN/SIGTTOU. + { + int leader = sys_fork(); + if (leader < 0) { + sys_write(1, "[init] fork(job control leader) failed\n", + (uint32_t)(sizeof("[init] fork(job control leader) failed\n") - 1)); + sys_exit(1); + } + if (leader == 0) { + int me = sys_getpid(); + int sid = sys_setsid(); + if (sid != me) { + sys_write(1, "[init] setsid(job control) failed\n", + (uint32_t)(sizeof("[init] setsid(job control) failed\n") - 1)); + sys_exit(1); + } + + int tfd = sys_open("/dev/tty", 0); + if (tfd < 0) { + sys_write(1, "[init] open(/dev/tty) for job control failed\n", + (uint32_t)(sizeof("[init] open(/dev/tty) for job control failed\n") - 1)); + sys_exit(1); + } + + // Touch ioctl to make kernel acquire controlling session/pgrp. + int fg = 0; + (void)sys_ioctl(tfd, TIOCGPGRP, &fg); + + fg = me; + if (sys_ioctl(tfd, TIOCSPGRP, &fg) < 0) { + sys_write(1, "[init] ioctl TIOCSPGRP(job control) failed\n", + (uint32_t)(sizeof("[init] ioctl TIOCSPGRP(job control) failed\n") - 1)); + sys_exit(1); + } + + int bg = sys_fork(); + if (bg < 0) { + sys_write(1, "[init] fork(job control bg) failed\n", + (uint32_t)(sizeof("[init] fork(job control bg) failed\n") - 1)); + sys_exit(1); + } + if (bg == 0) { + (void)sys_setpgid(0, me + 1); + + (void)sys_sigaction(SIGTTIN, ttin_handler, 0); + (void)sys_sigaction(SIGTTOU, ttou_handler, 0); + + uint8_t b = 0; + (void)sys_read(tfd, &b, 1); + if (!got_ttin) { + sys_write(1, "[init] SIGTTIN job control failed\n", + (uint32_t)(sizeof("[init] SIGTTIN job control failed\n") - 1)); + sys_exit(1); + } + + const char msg2[] = "x"; + (void)sys_write(tfd, msg2, 1); + if (!got_ttou) { + sys_write(1, "[init] SIGTTOU job control failed\n", + (uint32_t)(sizeof("[init] SIGTTOU job control failed\n") - 1)); + sys_exit(1); + } + + sys_exit(0); + } + + int st2 = 0; + int wp2 = sys_waitpid(bg, &st2, 0); + if (wp2 != bg || st2 != 0) { + sys_write(1, "[init] waitpid(job control bg) failed wp=", (uint32_t)(sizeof("[init] waitpid(job control bg) failed wp=") - 1)); + write_int_dec(wp2); + sys_write(1, " st=", (uint32_t)(sizeof(" st=") - 1)); + write_int_dec(st2); + sys_write(1, "\n", 1); + sys_exit(1); + } + + (void)sys_close(tfd); + sys_exit(0); + } + + int stL = 0; + int wpL = sys_waitpid(leader, &stL, 0); + if (wpL != leader || stL != 0) { + sys_write(1, "[init] waitpid(job control leader) failed wp=", (uint32_t)(sizeof("[init] waitpid(job control leader) failed wp=") - 1)); + write_int_dec(wpL); + sys_write(1, " st=", (uint32_t)(sizeof(" st=") - 1)); + write_int_dec(stL); + sys_write(1, "\n", 1); + sys_exit(1); + } + + sys_write(1, "[init] job control (SIGTTIN/SIGTTOU) OK\n", + (uint32_t)(sizeof("[init] job control (SIGTTIN/SIGTTOU) OK\n") - 1)); + } + { int fd = sys_open("/dev/null", 0); if (fd < 0) { @@ -810,6 +995,34 @@ void _start(void) { sys_write(1, "[init] setsid/setpgid/getpgrp OK\n", (uint32_t)(sizeof("[init] setsid/setpgid/getpgrp OK\n") - 1)); } + + { + uintptr_t oldh = 0; + if (sys_sigaction(SIGUSR1, usr1_handler, &oldh) < 0) { + sys_write(1, "[init] sigaction failed\n", + (uint32_t)(sizeof("[init] sigaction failed\n") - 1)); + sys_exit(1); + } + + int me = sys_getpid(); + if (sys_kill(me, SIGUSR1) < 0) { + sys_write(1, "[init] kill(SIGUSR1) failed\n", + (uint32_t)(sizeof("[init] kill(SIGUSR1) failed\n") - 1)); + sys_exit(1); + } + + for (uint32_t i = 0; i < 2000000U; i++) { + if (got_usr1) break; + } + + if (!got_usr1) { + sys_write(1, "[init] SIGUSR1 not delivered\n", + (uint32_t)(sizeof("[init] SIGUSR1 not delivered\n") - 1)); + sys_exit(1); + } + + sys_write(1, "[init] sigaction/kill(SIGUSR1) OK\n", + (uint32_t)(sizeof("[init] sigaction/kill(SIGUSR1) OK\n") - 1)); } fd = sys_open("/tmp/hello.txt", 0); @@ -965,8 +1178,7 @@ void _start(void) { sys_exit(1); } static const char z[] = "discard me"; - int wr = sys_write(fd, z, (uint32_t)(sizeof(z) - 1)); - if (wr != (int)(sizeof(z) - 1)) { + if (sys_write(fd, z, (uint32_t)(sizeof(z) - 1)) != (int)(sizeof(z) - 1)) { sys_write(1, "[init] /dev/null write failed\n", (uint32_t)(sizeof("[init] /dev/null write failed\n") - 1)); sys_exit(1);