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.
2DNPZFPNI2OM5FKYTC2KE5NKKKAP45AQ2VDDYLZZHCJ35X3EBJRQC NKQOEVVPWAT7UQ4JKOK7VWS6H3PKN52DDWT7SEWPK3JS743OGZNQC XCDTFZUYSOYEARMJCV4ORVQWG2VWZQ43HU2U63RBECP53OSCM2GQC KPKXKDNGVWQSM5D5ODNWZBBQDE3YT32CEAWIEYND62P26XHPKGTAC MBWLLEYE6JSCFRMC7YX4L7I6M4ETR77MPGKFGN5PTPZPRCUMC7RQC N4IROACVZ4MU73J5SM6WXJMKQSFR3VN5SOKENNNZNEGMTGB2Q3HAC 5AIYUMTBY6TFQTBRP3MJ2PYWUMRF57I77NIVWYE74UMEVQMBWZVQC DIEY5USNXFN6O2ARZ5IPBS2VX4OH7KE4RMX2JWAWTVMMSYA6GREAC MHVIT4JYWUYD4UCGB2AHLXWLX6B5SYE22BREERNGANT7RGGDUFOAC LVQXQIYA7QMLVYOANYEFHDBTFAOSE3D2IYAVOG2DXURTASRCUNYQC 73YR46NJNYZQKHA3QDJCAZYAKC2CGEF5LIS44NOIPDZU6FX6BDPQC DKJFD6JNNK5LJMRGQABMJZKMFZLGY3ADKJWF6J4BBHEUPY3NB67QC BG6PEOB2M2Y56QPVMELU7VNNCGNMSQ2K6ATBUCPJLKPLTDWNJQ5AC EHEQ4AY3JT6CTIANKZMMS5MZ5P5BFC7GWYN4VMSYY2FR3PW4UL7AC WE5Q2NVIIK4R2DUUZYLJFQVYK5O26EDEJRPK3CPGWHU3SEAC2DQAC HJOEIMLRDVQ2KZI5HGL2HKGBM3AHP7YIKGKDAGFUNKRUXVRB24NAC {auto activeStepState(activeStep->state_.lock());if (activeStepState->cancelled) throw Error("step cancelled");activeStepState->pid = child.pid;}Finally clearPid([&]() {auto activeStepState(activeStep->state_.lock());activeStepState->pid = -1;/* FIXME: there is a slight race here with stepcancellation in State::processQueueChange(), whichcould call kill() on this pid after we've done waitpid()on it. With pid wrap-around, there is a tinypossibility that we end up killing anotherprocess. Meh. */});
State::StepResult State::doBuildStep(nix::ref<Store> destStore, Step::ptr step,Machine::ptr machine)
State::StepResult State::doBuildStep(nix::ref<Store> destStore,MachineReservation::ptr reservation,std::shared_ptr<ActiveStep> activeStep)
result.stepStatus = bsAborted;result.errorMsg = e.msg();result.canRetry = true;} catch (__cxxabiv1::__forced_unwind & e) {/* The queue monitor thread cancelled this step. */try {
if (activeStep->state_.lock()->cancelled) {
pqxx::work txn(*conn);finishBuildStep(txn, result.startTime, time(0), result.overhead, buildId,stepNr, machine->sshName, bsCancelled, "");txn.commit();stepFinished = true;} catch (...) {ignoreException();
result.stepStatus = bsCancelled;result.canRetry = false;} else {result.stepStatus = bsAborted;result.errorMsg = e.msg();result.canRetry = true;
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));}}