Mercurial > hg > svapp
comparison framework/Align.cpp @ 718:464fed3096f5
Avoid deadlock when process finishes immediately (so alignmentProgramFinished is called from waitForStarted while mutex already held)
author | Chris Cannam |
---|---|
date | Thu, 31 Oct 2019 11:28:35 +0000 |
parents | d2e8e9788cd4 |
children |
comparison
equal
deleted
inserted
replaced
717:d2e8e9788cd4 | 718:464fed3096f5 |
---|---|
485 ModelId referenceId, | 485 ModelId referenceId, |
486 ModelId otherId, | 486 ModelId otherId, |
487 QString program, | 487 QString program, |
488 QString &error) | 488 QString &error) |
489 { | 489 { |
490 QMutexLocker locker (&m_mutex); | |
491 | |
492 // Run an external program, passing to it paths to the main | 490 // Run an external program, passing to it paths to the main |
493 // model's audio file and the new model's audio file. It returns | 491 // model's audio file and the new model's audio file. It returns |
494 // the path in CSV form through stdout. | 492 // the path in CSV form through stdout. |
495 | 493 |
496 auto reference = ModelById::getAs<ReadOnlyWaveFileModel>(referenceId); | 494 auto reference = ModelById::getAs<ReadOnlyWaveFileModel>(referenceId); |
517 if (refPath == "" || otherPath == "") { | 515 if (refPath == "" || otherPath == "") { |
518 error = "Failed to find local filepath for wave-file model"; | 516 error = "Failed to find local filepath for wave-file model"; |
519 return false; | 517 return false; |
520 } | 518 } |
521 | 519 |
522 auto alignmentModel = | 520 QProcess *process = nullptr; |
523 std::make_shared<AlignmentModel>(referenceId, otherId, ModelId()); | 521 ModelId alignmentModelId = {}; |
524 auto alignmentModelId = ModelById::add(alignmentModel); | 522 |
525 other->setAlignment(alignmentModelId); | 523 { |
526 | 524 QMutexLocker locker (&m_mutex); |
527 QProcess *process = new QProcess; | 525 |
528 process->setProcessChannelMode(QProcess::ForwardedErrorChannel); | 526 auto alignmentModel = |
527 std::make_shared<AlignmentModel>(referenceId, otherId, ModelId()); | |
528 | |
529 alignmentModelId = ModelById::add(alignmentModel); | |
530 other->setAlignment(alignmentModelId); | |
531 | |
532 process = new QProcess; | |
533 process->setProcessChannelMode(QProcess::ForwardedErrorChannel); | |
534 | |
535 connect(process, | |
536 SIGNAL(finished(int, QProcess::ExitStatus)), | |
537 this, | |
538 SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); | |
539 | |
540 m_pendingProcesses[process] = alignmentModelId; | |
541 } | |
529 | 542 |
530 QStringList args; | 543 QStringList args; |
531 args << refPath << otherPath; | 544 args << refPath << otherPath; |
532 | |
533 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), | |
534 this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); | |
535 | |
536 m_pendingProcesses[process] = alignmentModelId; | |
537 | 545 |
538 SVCERR << "Align::alignModelViaProgram: Starting program \"" | 546 SVCERR << "Align::alignModelViaProgram: Starting program \"" |
539 << program << "\" with args: "; | 547 << program << "\" with args: "; |
540 for (auto a: args) { | 548 for (auto a: args) { |
541 SVCERR << "\"" << a << "\" "; | 549 SVCERR << "\"" << a << "\" "; |
544 | 552 |
545 process->start(program, args); | 553 process->start(program, args); |
546 | 554 |
547 bool success = process->waitForStarted(); | 555 bool success = process->waitForStarted(); |
548 | 556 |
549 if (!success) { | 557 { |
550 SVCERR << "ERROR: Align::alignModelViaProgram: Program did not start" | 558 QMutexLocker locker(&m_mutex); |
551 << endl; | 559 |
552 error = "Alignment program \"" + program + "\" could not be executed"; | 560 if (!success) { |
553 m_pendingProcesses.erase(process); | 561 |
554 other->setAlignment({}); | 562 SVCERR << "ERROR: Align::alignModelViaProgram: " |
555 ModelById::release(alignmentModelId); | 563 << "Program did not start" << endl; |
556 delete process; | 564 error = "Alignment program \"" + program + "\" did not start"; |
557 } else { | 565 |
558 doc->addNonDerivedModel(alignmentModelId); | 566 m_pendingProcesses.erase(process); |
567 other->setAlignment({}); | |
568 ModelById::release(alignmentModelId); | |
569 delete process; | |
570 | |
571 } else { | |
572 doc->addNonDerivedModel(alignmentModelId); | |
573 } | |
559 } | 574 } |
560 | 575 |
561 return success; | 576 return success; |
562 } | 577 } |
563 | 578 |