Browse Source

Shell: Kill existing jobs when exiting

AnotherTest 5 years ago
parent
commit
143be7234f
2 changed files with 41 additions and 0 deletions
  1. 40 0
      Shell/Shell.cpp
  2. 1 0
      Shell/Shell.h

+ 40 - 0
Shell/Shell.cpp

@@ -337,6 +337,7 @@ int Shell::builtin_dirs(int argc, const char** argv)
 
 int Shell::builtin_exit(int, const char**)
 {
+    stop_all_jobs();
     printf("Good-bye!\n");
     exit(0);
     return 0;
@@ -1744,5 +1745,44 @@ Shell::Shell()
 
 Shell::~Shell()
 {
+    stop_all_jobs();
     save_history();
 }
+
+void Shell::stop_all_jobs()
+{
+    if (!jobs.is_empty()) {
+        printf("Killing active jobs\n");
+        for (auto& entry : jobs) {
+            if (!entry.value->is_running_in_background()) {
+#ifdef SH_DEBUG
+                dbg() << "Job " << entry.value->pid() << " is not running in background";
+#endif
+                if (killpg(entry.value->pgid(), SIGCONT) < 0) {
+                    perror("killpg(CONT)");
+                }
+            }
+
+            if (killpg(entry.value->pgid(), SIGHUP) < 0) {
+                perror("killpg(HUP)");
+            }
+
+            if (killpg(entry.value->pgid(), SIGTERM) < 0) {
+                perror("killpg(TERM)");
+            }
+        }
+
+        usleep(10000); // Wait for a bit before killing the job
+
+        for (auto& entry : jobs) {
+#ifdef SH_DEBUG
+            dbg() << "Actively killing " << entry.value->pid() << "(" << entry.value->cmd() << ")";
+#endif
+            if (killpg(entry.value->pgid(), SIGKILL) < 0) {
+                if (errno == ESRCH)
+                    continue; // The process has exited all by itself.
+                perror("killpg(KILL)");
+            }
+        }
+    }
+}

+ 1 - 0
Shell/Shell.h

@@ -162,6 +162,7 @@ private:
     };
 
     void cache_path();
+    void stop_all_jobs();
 
     IterationDecision wait_for_pid(const SpawnedProcess&, bool is_first_command_in_chain, int& return_value);