Forráskód Böngészése

Fix bug where a signal-interrupted waitpid() wouldn't return EINTR.

Andreas Kling 6 éve
szülő
commit
f5a83c4d8a
3 módosított fájl, 15 hozzáadás és 9 törlés
  1. 7 4
      Kernel/Process.cpp
  2. 2 2
      Kernel/Process.h
  3. 6 3
      Kernel/Scheduler.cpp

+ 7 - 4
Kernel/Process.cpp

@@ -1464,7 +1464,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
         }
     }
 
-    m_waitee = waitee;
+    m_waitee_pid = waitee;
     block(BlockedWait);
     sched_yield();
     if (m_was_interrupted_while_blocked)
@@ -1472,17 +1472,20 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
     Process* waitee_process;
     {
         InterruptDisabler disabler;
-
         // NOTE: If waitee was -1, m_waitee will have been filled in by the scheduler.
-        waitee_process = Process::from_pid(m_waitee);
+        waitee_process = Process::from_pid(m_waitee_pid);
     }
     ASSERT(waitee_process);
     exit_status = reap(*waitee_process);
-    return m_waitee;
+    return m_waitee_pid;
 }
 
 void Process::unblock()
 {
+    if (current == this) {
+        kprintf("ignoring unblock() on current, %s(%u) {%s}\n", name().characters(), pid(), toString(state()));
+        return;
+    }
     ASSERT(m_state != Process::Runnable && m_state != Process::Running);
     system.nblocked--;
     m_state = Process::Runnable;

+ 2 - 2
Kernel/Process.h

@@ -187,7 +187,7 @@ public:
     void did_schedule() { ++m_timesScheduled; }
     dword timesScheduled() const { return m_timesScheduled; }
 
-    pid_t waitee() const { return m_waitee; }
+    pid_t waitee_pid() const { return m_waitee_pid; }
 
     dword framePtr() const { return m_tss.ebp; }
     dword stackPtr() const { return m_tss.esp; }
@@ -265,7 +265,7 @@ private:
     int m_error { 0 };
     void* m_kernelStack { nullptr };
     dword m_timesScheduled { 0 };
-    pid_t m_waitee { -1 };
+    pid_t m_waitee_pid { -1 };
     int m_fdBlockedOnRead { -1 };
     int m_blocked_fd { -1 };
     size_t m_max_open_file_descriptors { 16 };

+ 6 - 3
Kernel/Scheduler.cpp

@@ -38,8 +38,8 @@ bool Scheduler::pick_next()
             process.for_each_child([&process] (Process& child) {
                 if (child.state() != Process::Dead)
                     return true;
-                if (process.waitee() == -1 || process.waitee() == child.pid()) {
-                    process.m_waitee = child.pid();
+                if (process.waitee_pid() == -1 || process.waitee_pid() == child.pid()) {
+                    process.m_waitee_pid = child.pid();
                     process.unblock();
                     return false;
                 }
@@ -99,9 +99,12 @@ bool Scheduler::pick_next()
         //        syscall effectively being "interrupted" despite having completed?
         if (process.in_kernel() && !process.is_blocked())
             return true;
+        // NOTE: dispatch_one_pending_signal() may unblock the process.
+        bool was_blocked = process.is_blocked();
         if (!process.dispatch_one_pending_signal())
             return true;
-        if (process.is_blocked()) {
+        if (was_blocked) {
+            dbgprintf("Unblock %s(%u) due to signal\n", process.name().characters(), process.pid());
             process.m_was_interrupted_while_blocked = true;
             process.unblock();
         }