Skip to content

Conversation

@hexagonal-sun
Copy link
Owner

@hexagonal-sun hexagonal-sun commented Jan 16, 2026

Fixes: #59

  • thread_group: pgid: inherit from parent
    Inherit the process-group ID from the parent. If there is no parent
    specified then the pgid is the same as the tgid.

  • fd_table: don't close CLOEXEC FDs until exec
    Currently we close CLOEXEC FDs when we call clone() when making a copy
    of the file descriptor table. Defer this until the exec syscall.

    This fixes numerous bugs, namely with bash and setting the foreground
    process group for the current TTY.

  • thread_group: deliver_signal: ensure signal delivery
    If all tasks within a thread group are sleeping when a signal is
    delivered, wake at least one task to action the signal.

  • libkernel: error: add Interrupted
    Add the Interrupted discriminant for the KernelError enum. Also map
    it to Linux's EINTR error value.

  • process: peek_signal: new
    Add a new function that allows for peeking at a task's currently pending
    signals without consuming the signal.

  • process: signals: add interruptable()
    Add a new struct, InterruptableFut which allows signal
    short-circuiting logic. If a future within the kernel's syscall logic is
    wrapped in a InterruptableFut, then a wakeup with any pending signals
    causes the underlying future to be dropped and it's operation cancelled.

    Provide a InterruptResult enum to allow the caller to know whether the
    operation was interrupted and allows them to take appropriate action.
    Typically exiting with -EINTR.

    Finally, provide a blanket implementation for all futures, allowing then
    to call .interruptable() to easily wrap any future.

  • usertest: make sleep interruptable()
    Allow the nanosleep family of functions to be interrupted. When an
    interruption occures, calculation the remaining duration and write that
    back to user-space.

    Add a test to ensure proper functionality into usertest.

  • pipe: read: allow interruption
    Allow interrupt for read() calls on a pipe. If the syscall is
    interrupted simply return -EINVAL.

    Add a testcase to usertest for this case.

  • tty: read: allow interruption
    Allow a read() on a tty to be interrupted by a syscall. This is the
    fundamental fix for making '^C' interrupt a process like cat when it's
    reading from stdin.

  • sched: remove force_resched()
    This function is used to force the scheduler to reschedule another task,
    avoiding the fast-path exit. Given the sheer number of task state
    change points in the code, the fast-path exit code has become too
    brittle.

    Instead, check that the current task's state is still Running before
    taking the fast-path short-circuit. The cost of one spinlock uncontended
    lock-unlock cycle is worth the cost of avoiding many subtle scheduling
    logic bugs.

  • sys_wait4: make interruptable
    Make the sys_wait4 system call interruptable via signal delivery.

    Also include some a test in usertest to ensure proper functionality.

Inherit the process-group ID from the parent. If there is no parent
specified then the pgid is the same as the tgid.
Currently we close CLOEXEC FDs when we call `clone()` when making a copy
of the file descriptor table. Defer this until the `exec` syscall.

This fixes numerous bugs, namely with bash and setting the foreground
process group for the current TTY.
If all tasks within a thread group are sleeping when a signal is
delivered, wake at least one task to action the signal.
Add the `Interrupted` discriminant for the `KernelError` enum. Also map
it to Linux's `EINTR` error value.
Add a new function that allows for peeking at a task's currently pending
signals without consuming the signal.
Add a new struct, `InterruptableFut` which allows signal
short-circuiting logic. If a future within the kernel's syscall logic is
wrapped in a `InterruptableFut`, then a wakeup with any pending signals
causes the underlying future to be dropped and it's operation cancelled.

Provide a `InterruptResult` enum to allow the caller to know whether the
operation was interrupted and allows them to take appropriate action.
Typically exiting with `-EINTR`.

Finally, provide a blanket implementation for all futures, allowing then
to call `.interruptable()` to easily wrap any future.
Allow the `nanosleep` family of functions to be interrupted. When an
interruption occures, calculation the remaining duration and write that
back to user-space.

Add a test to ensure proper functionality into usertest.
Allow interrupt for `read()` calls on a pipe.  If the syscall is
interrupted simply return `-EINVAL`.

Add a testcase to `usertest` for this case.
Allow a `read()` on a tty to be interrupted by a syscall. This is the
fundamental fix for making '^C' interrupt a process like `cat` when it's
reading from `stdin`.
This function is used to force the scheduler to reschedule another task,
avoiding the fast-path exit.  Given the sheer number of task state
change points in the code, the fast-path exit code has become too
brittle.

Instead, check that the current task's state is still `Running` before
taking the fast-path short-circuit. The cost of one spinlock uncontended
lock-unlock cycle is worth the cost of avoiding many subtle scheduling
logic bugs.
Make the `sys_wait4` system call interruptable via signal delivery.

Also include some a test in `usertest` to ensure proper functionality.
@hexagonal-sun hexagonal-sun merged commit abccd32 into master Jan 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ctrl-C doesn't work

3 participants