瀏覽代碼

Implement waitpid() support for getting the waitee's exit code.

Andreas Kling 6 年之前
父節點
當前提交
ec07761d0f
共有 7 個文件被更改,包括 33 次插入10 次删除
  1. 1 1
      Kernel/Syscall.cpp
  2. 13 3
      Kernel/Task.cpp
  3. 2 1
      Kernel/Task.h
  4. 二進制
      Kernel/_fs_contents
  5. 2 2
      LibC/unistd.cpp
  6. 5 1
      LibC/unistd.h
  7. 10 2
      Userland/sh.cpp

+ 1 - 1
Kernel/Syscall.cpp

@@ -95,7 +95,7 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
     case Syscall::PosixGetpid:
         return current->sys$getpid();
     case Syscall::PosixWaitpid:
-        return current->sys$waitpid((pid_t)arg1);
+        return current->sys$waitpid((pid_t)arg1, (int*)arg2, (int)arg3);
     case Syscall::PosixMmap:
         return (dword)current->sys$mmap((void*)arg1, (size_t)arg2);
     case Syscall::PosixMunmap:

+ 13 - 3
Kernel/Task.cpp

@@ -450,8 +450,13 @@ void Task::sys$exit(int status)
 
     s_tasks->remove(this);
 
+    for (auto* task = s_tasks->head(); task; task = task->next()) {
+        if (task->waitee() == m_pid)
+            task->m_waiteeStatus = status << 8;
+    }
+
     if (!scheduleNewTask()) {
-        kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
+        kprintf("Task::sys$exit: Failed to schedule a new task :(\n");
         HANG;
     }
 
@@ -752,7 +757,6 @@ int Task::sys$chdir(const char* path)
     if (!handle->isDirectory())
         return -ENOTDIR;
     m_cwd = handle->vnode();
-    kprintf("m_cwd <- %p (%u)\n", m_cwd.ptr(), handle->vnode()->inode.index());
     return 0;
 }
 
@@ -844,14 +848,20 @@ pid_t Task::sys$getpid()
     return m_pid;
 }
 
-pid_t Task::sys$waitpid(pid_t waitee)
+pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
 {
+    if (wstatus)
+        VALIDATE_USER_BUFFER(wstatus, sizeof(int));
+
     InterruptDisabler disabler;
     if (!Task::fromPID(waitee))
         return -1;
     m_waitee = waitee;
+    m_waiteeStatus = 0;
     block(BlockedWait);
     yield();
+    if (wstatus)
+        *wstatus = m_waiteeStatus;
     return m_waitee;
 }
 

+ 2 - 1
Kernel/Task.h

@@ -95,7 +95,7 @@ public:
     int sys$geterror() { return m_error; }
     void sys$exit(int status);
     int sys$spawn(const char* path, const char** args);
-    pid_t sys$waitpid(pid_t);
+    pid_t sys$waitpid(pid_t, int* wstatus, int options);
     void* sys$mmap(void*, size_t size);
     int sys$munmap(void*, size_t size);
     int sys$get_dir_entries(int fd, void*, size_t);
@@ -160,6 +160,7 @@ private:
     void* m_kernelStack { nullptr };
     dword m_timesScheduled { 0 };
     pid_t m_waitee { -1 };
+    int m_waiteeStatus { 0 };
     int m_fdBlockedOnRead { -1 };
     size_t m_maxFileHandles { 16 };
 

二進制
Kernel/_fs_contents


+ 2 - 2
LibC/unistd.cpp

@@ -39,9 +39,9 @@ int close(int fd)
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
 
-pid_t waitpid(pid_t waitee)
+pid_t waitpid(pid_t waitee, int* wstatus, int options)
 {
-    int rc = Syscall::invoke(Syscall::PosixWaitpid, waitee);
+    int rc = Syscall::invoke(Syscall::PosixWaitpid, waitee, (dword)wstatus);
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
 

+ 5 - 1
LibC/unistd.h

@@ -10,13 +10,17 @@ pid_t getpid();
 int open(const char* path);
 ssize_t read(int fd, void* buf, size_t count);
 int close(int fd);
-pid_t waitpid(pid_t);
+pid_t waitpid(pid_t, int* wstatus, int options);
 int chdir(const char* path);
 char* getcwd(char* buffer, size_t size);
 int lstat(const char* path, stat* statbuf);
 int sleep(unsigned seconds);
 int gethostname(char*, size_t);
 
+#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
+#define WTERMSIG(status) ((status) & 0x7f)
+#define WIFEXITED(status) (WTERMSIG(status) == 0)
+
 #define HOST_NAME_MAX 64
 
 #define	S_IFMT 0170000

+ 10 - 2
Userland/sh.cpp

@@ -17,7 +17,8 @@ static void prompt()
 
 static int sh_pwd(int, const char**)
 {
-    printf("cwd: %s\n", g_cwd);
+    printf("%s\n", g_cwd);
+    return 0;
 }
 
 static int sh_cd(int argc, const char** argv)
@@ -100,7 +101,14 @@ static int runcmd(char* cmd)
         return 1;
     }
     // FIXME: waitpid should give us the spawned process's exit status
-    waitpid(ret);
+    int wstatus = 0;
+    waitpid(ret, &wstatus, 0);
+
+    if (WIFEXITED(wstatus)) {
+        //printf("Exited normally with status %d\n", WEXITSTATUS(wstatus));
+    } else {
+        printf("Exited abnormally\n");
+    }
     return retval;
 }