-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Kill build hook with SIGTERM instead of SIGKILL #15105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,8 @@ | |
| #include <future> | ||
| #include <iostream> | ||
| #include <sstream> | ||
| #include <thread> | ||
| #include <atomic> | ||
| using namespace std::chrono_literals; | ||
|
|
||
| #include <grp.h> | ||
| #include <sys/types.h> | ||
|
|
@@ -75,6 +76,20 @@ int Pid::kill(bool allowInterrupts) | |
|
|
||
| debug("killing process %1%", pid); | ||
|
|
||
| std::atomic<bool> killed = false; | ||
|
|
||
| if (killTimeout > 0ms && killSignal != SIGKILL) | ||
| killThread = std::thread([&]() { | ||
| auto elapsed = 0ms; | ||
| while (elapsed < killTimeout) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will block the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In an ideal world we could try doing async cleanup if we had better facilities for async things (think a task that either polls pidfd or hits a timeout). I think ASIO + Boost.process2 might have some helpers for this sort of thing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only if these conditions are met:
|
||
| std::this_thread::sleep_for(25ms); | ||
| elapsed += 25ms; | ||
| if (killed) | ||
| return; | ||
| } | ||
| ::kill(separatePG ? -pid : pid, SIGKILL); | ||
| }); | ||
|
|
||
| /* Send the requested signal to the child. If it has its own | ||
| process group, send the signal to every process in the child | ||
| process group (which hopefully includes *all* its children). */ | ||
|
|
@@ -88,7 +103,12 @@ int Pid::kill(bool allowInterrupts) | |
| logError(SysError("killing process %d", pid).info()); | ||
| } | ||
|
|
||
| return wait(allowInterrupts); | ||
| int ret = wait(allowInterrupts); | ||
| if (killThread.joinable()) { | ||
| killed = true; | ||
| killThread.join(); | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| int Pid::wait(bool allowInterrupts) | ||
|
|
@@ -118,6 +138,11 @@ void Pid::setKillSignal(int signal) | |
| this->killSignal = signal; | ||
| } | ||
|
|
||
| void Pid::setKillTimeout(std::chrono::milliseconds duration) | ||
| { | ||
| this->killTimeout = duration; | ||
| } | ||
|
|
||
| pid_t Pid::release() | ||
| { | ||
| pid_t p = pid; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm doesn't this mean that we'd use SIGTERM in the destructor and could get stuck on waitpid after an interrupt indefinitely for a misbehaving build hook? Shouldn't we still use SIGKILL in the destructor and have a timeout in the happy path (busywait?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How's this? The alternative is adding a busywait + kill directly to Pid::wait, which seems messy.