/// /// Copyright 2019-2020 Oliver Giles /// /// This file is part of Laminar /// /// Laminar is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License as published by /// the Free Software Foundation, either version 3 of the License, or /// (at your option) any later version. /// /// Laminar is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with Laminar. If not, see /// #include "log.h" #include #include #include #include #if defined(__FreeBSD__) #include #else #include #endif #include #include #include #include #include #include "run.h" // short syntax helper for kj::Path template inline kj::Path operator/(const kj::Path& p, const T& ext) { return p.append(ext); } template inline kj::Path operator/(const kj::PathPtr& p, const T& ext) { return p.append(ext); } struct Script { kj::Path path; kj::Path cwd; bool runOnAbort; }; static void aggressive_recursive_kill(pid_t parent) { DIR* proc = opendir("/proc"); if(!proc) return; while(struct dirent* de = readdir(proc)) { if(!isdigit(*de->d_name)) continue; char status_file[640]; sprintf(status_file, "/proc/%s/status", de->d_name); FILE* status_fp = fopen(status_file, "rb"); if(!status_fp) continue; char status_buffer[512]; int n = fread(status_buffer, 1, 512, status_fp); if(char* p = (char*)memmem(status_buffer, n, "PPid:\t", 6)) { pid_t ppid = strtol(p + 6, NULL, 10); if(ppid == parent) { pid_t pid = atoi(de->d_name); aggressive_recursive_kill(pid); fprintf(stderr, "[laminar] sending SIGKILL to pid %d\n", pid); kill(pid, SIGKILL); } } fclose(status_fp); } closedir(proc); } class Leader final : public kj::TaskSet::ErrorHandler { public: Leader(kj::AsyncIoContext& ioContext, kj::Filesystem& fs, const char* jobName, uint runNumber); RunState run(); private: void taskFailed(kj::Exception&& exception) override; kj::Promise step(std::queue