From ef3c036f495b62625001183c34f724b233ec1b07 Mon Sep 17 00:00:00 2001 From: 0xboobface <0xboobface@gmail.com> Date: Sun, 10 May 2020 14:58:42 +0200 Subject: [PATCH] Fix race condition causing orphaned FFmpeg processes The problem was, that an error occured before FFmpeg was completely launched. ctbrec called internalStop, but the FFmpeg fields still pointed to null. ctbrec then finished the recording. In the meantime FFmpeg fired up and was abandoned by the recording. --- .../download/hls/MergedFfmpegHlsDownload.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java index 4343e52e..0647682e 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java @@ -51,6 +51,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload { private transient Process ffmpeg; private transient OutputStream ffmpegStdIn; private transient Thread ffmpegThread; + private transient Object ffmpegStartMonitor = new Object(); public MergedFfmpegHlsDownload(HttpClient client) { super(client); @@ -85,9 +86,21 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload { Files.createDirectories(targetFile.getParentFile().toPath()); startFfmpegProcess(targetFile); + synchronized (ffmpegStartMonitor) { + int tries = 0; + while (ffmpeg == null && tries++ < 15) { + LOG.debug("Waiting for FFmpeg to spawn to record {}", model.getName()); + ffmpegStartMonitor.wait(1000); + } + } - downloadSegments(segments, true); - ffmpegThread.join(); + if (ffmpeg == null) { + throw new ProcessExitedUncleanException("Couldn't spawn FFmpeg"); + } else { + LOG.debug("Starting to download segments"); + downloadSegments(segments, true); + ffmpegThread.join(); + } } catch (ParseException e) { throw new IOException("Couldn't parse stream information", e); } catch (PlaylistException e) { @@ -125,6 +138,9 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload { LOG.debug("Command line: {}", Arrays.toString(cmdline)); ffmpeg = Runtime.getRuntime().exec(cmdline, new String[0], target.getParentFile()); + synchronized (ffmpegStartMonitor) { + ffmpegStartMonitor.notifyAll(); + } ffmpegStdIn = ffmpeg.getOutputStream(); int exitCode = 1; File ffmpegLog = File.createTempFile(target.getName(), ".log");