Step cancellation: Don't use pthread_cancel()
This was a bad idea because pthread_cancel() is unsalvageable broken in C++. Destructors are not allowed to throw exceptions (especially in C++11), but pthread_cancel() can cause a __cxxabiv1::__forced_unwind exception inside any destructor that invokes a cancellation point. (This exception can be caught but *must* be rethrown.) So let's just kill the builder process instead.
This commit is contained in:
@ -337,20 +337,23 @@ void State::processQueueChange(Connection & conn)
|
||||
{
|
||||
auto activeSteps(activeSteps_.lock());
|
||||
for (auto & activeStep : *activeSteps) {
|
||||
auto threadId = activeStep->threadId; // FIXME: use Sync or atomic?
|
||||
if (threadId == 0) continue;
|
||||
|
||||
std::set<Build::ptr> dependents;
|
||||
std::set<Step::ptr> steps;
|
||||
getDependents(activeStep->step, dependents, steps);
|
||||
if (!dependents.empty()) continue;
|
||||
|
||||
printInfo("cancelling thread for build step ‘%s’", activeStep->step->drvPath);
|
||||
|
||||
int err = pthread_cancel(threadId);
|
||||
if (err)
|
||||
printError("error cancelling thread for build step ‘%s’: %s",
|
||||
activeStep->step->drvPath, strerror(err));
|
||||
{
|
||||
auto activeStepState(activeStep->state_.lock());
|
||||
if (activeStepState->cancelled) continue;
|
||||
activeStepState->cancelled = true;
|
||||
if (activeStepState->pid != -1) {
|
||||
printInfo("killing builder process %d of build step ‘%s’",
|
||||
activeStepState->pid, activeStep->step->drvPath);
|
||||
if (kill(activeStepState->pid, SIGINT) == -1)
|
||||
printError("error killing build step ‘%s’: %s",
|
||||
activeStep->step->drvPath, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user