From 91d91eac0d4e1abad1776c91bf3c985b2b9c69ad Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 15 Dec 2024 16:31:43 +0100 Subject: [PATCH] Fix export encoder race condition The CmdPipeWriter::Terminated signal is used to trigger the FileWritten callback, which invokes ExportGraphBuilder::Encoder::copy_files Encoder::filenames must not be destroyed before the callback arrives. This is now guaranteed by the Encoder d'tor waiting for for the encode process to terminate. --- libs/ardour/ardour/export_graph_builder.h | 3 ++- libs/ardour/export_graph_builder.cc | 7 +++++++ libs/audiographer/audiographer/general/cmdpipe_writer.h | 7 +++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/export_graph_builder.h b/libs/ardour/ardour/export_graph_builder.h index 5ba13de5f0..5f9e1beec3 100644 --- a/libs/ardour/ardour/export_graph_builder.h +++ b/libs/ardour/ardour/export_graph_builder.h @@ -120,7 +120,8 @@ class LIBARDOUR_API ExportGraphBuilder void add_split_config (FileSpec const & config); class Encoder { - public: + public: + ~Encoder (); template std::shared_ptr > init (FileSpec const & new_config); void add_child (FileSpec const & new_config); void remove_children (); diff --git a/libs/ardour/export_graph_builder.cc b/libs/ardour/export_graph_builder.cc index 82706337b0..7b98725aa3 100644 --- a/libs/ardour/export_graph_builder.cc +++ b/libs/ardour/export_graph_builder.cc @@ -380,6 +380,13 @@ ExportGraphBuilder::Encoder::add_child (FileSpec const & new_config) filenames.push_back (new_config.filename); } +ExportGraphBuilder::Encoder::~Encoder () +{ + if (pipe_writer) { + pipe_writer->flush (); + } +} + void ExportGraphBuilder::Encoder::destroy_writer (bool delete_out_file) { diff --git a/libs/audiographer/audiographer/general/cmdpipe_writer.h b/libs/audiographer/audiographer/general/cmdpipe_writer.h index 867b7f3464..1ddd9f80db 100644 --- a/libs/audiographer/audiographer/general/cmdpipe_writer.h +++ b/libs/audiographer/audiographer/general/cmdpipe_writer.h @@ -59,6 +59,12 @@ public: samplecnt_t get_samples_written() const { return samples_written; } void reset_samples_written_count() { samples_written = 0; } + void flush (void) + { + _proc->close_stdin (); + _proc->wait (); + } + void close (void) { _proc->terminate (); @@ -93,6 +99,7 @@ public: if (_proc->start (ARDOUR::SystemExec::ShareWithParent)) { throw ARDOUR::ExportFailed ("External encoder (ffmpeg) cannot be started."); } + assert (_proc->is_running ()); } else { _proc->close_stdin (); }