diff options
Diffstat (limited to 'Kernel/Process.cpp')
-rw-r--r-- | Kernel/Process.cpp | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index e3ec87a198..5bd8de15e6 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1369,7 +1369,7 @@ ssize_t Process::do_write(FileDescription& description, const u8* data, int data #ifdef IO_DEBUG dbgprintf("block write on %d\n", fd); #endif - if (current->block<Thread::WriteBlocker>(description) == Thread::BlockResult::InterruptedBySignal) { + if (current->block<Thread::WriteBlocker>(description) != Thread::BlockResult::WokeNormally) { if (nwritten == 0) return -EINTR; } @@ -1430,7 +1430,7 @@ ssize_t Process::sys$read(int fd, u8* buffer, ssize_t size) return -EISDIR; if (description->is_blocking()) { if (!description->can_read()) { - if (current->block<Thread::ReadBlocker>(*description) == Thread::BlockResult::InterruptedBySignal) + if (current->block<Thread::ReadBlocker>(*description) != Thread::BlockResult::WokeNormally) return -EINTR; } } @@ -2042,7 +2042,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) } pid_t waitee_pid = waitee; - if (current->block<Thread::WaitBlocker>(options, waitee_pid) == Thread::BlockResult::InterruptedBySignal) + if (current->block<Thread::WaitBlocker>(options, waitee_pid) != Thread::BlockResult::WokeNormally) return -EINTR; InterruptDisabler disabler; @@ -2445,7 +2445,7 @@ int Process::sys$select(const Syscall::SC_select_params* params) #endif if (!timeout || select_has_timeout) { - if (current->block<Thread::SelectBlocker>(computed_timeout, select_has_timeout, rfds, wfds, efds) == Thread::BlockResult::InterruptedBySignal) + if (current->block<Thread::SelectBlocker>(computed_timeout, select_has_timeout, rfds, wfds, efds) != Thread::BlockResult::WokeNormally) return -EINTR; } @@ -2505,7 +2505,7 @@ int Process::sys$poll(pollfd* fds, int nfds, int timeout) #endif if (has_timeout || timeout < 0) { - if (current->block<Thread::SelectBlocker>(actual_timeout, has_timeout, rfds, wfds, Thread::SelectBlocker::FDVector()) == Thread::BlockResult::InterruptedBySignal) + if (current->block<Thread::SelectBlocker>(actual_timeout, has_timeout, rfds, wfds, Thread::SelectBlocker::FDVector()) != Thread::BlockResult::WokeNormally) return -EINTR; } @@ -2811,7 +2811,7 @@ int Process::sys$accept(int accepting_socket_fd, sockaddr* address, socklen_t* a auto& socket = *accepting_socket_description->socket(); if (!socket.can_accept()) { if (accepting_socket_description->is_blocking()) { - if (current->block<Thread::AcceptBlocker>(*accepting_socket_description) == Thread::BlockResult::InterruptedBySignal) + if (current->block<Thread::AcceptBlocker>(*accepting_socket_description) != Thread::BlockResult::WokeNormally) return -EINTR; } else { return -EAGAIN; @@ -3358,9 +3358,18 @@ int Process::sys$join_thread(int tid, void** exit_value) void* joinee_exit_value = nullptr; - // FIXME: pthread_join() should not be interruptable. Enforce this somehow? - auto result = current->block<Thread::JoinBlocker>(*thread, joinee_exit_value); - (void)result; + // NOTE: pthread_join() cannot be interrupted by signals. Only by death. + for (;;) { + auto result = current->block<Thread::JoinBlocker>(*thread, joinee_exit_value); + if (result == Thread::BlockResult::InterruptedByDeath) { + // NOTE: This cleans things up so that Thread::finalize() won't + // get confused about a missing joiner when finalizing the joinee. + InterruptDisabler disabler; + current->m_joinee->m_joiner = nullptr; + current->m_joinee = nullptr; + return 0; + } + } // NOTE: 'thread' is very possibly deleted at this point. Clear it just to be safe. thread = nullptr; |