Skip to content
Browse files

Fixed possible race condition causing broken playback.

  • Loading branch information...
1 parent 815ecf1 commit 18edeaf82719100b7185ea35eafcbb6da000a136 @Raptor399 Raptor399 committed
View
3 CHANGELOG.txt
@@ -3,6 +3,9 @@ Changelog:
1.90.2 - 2013-??-??
+ Misc:
+ - Fixed possible race condition causing broken playback
+
1.90.1 - 2013-08-17
Engines:
View
6 src/main/java/net/pms/encoders/FFmpegWebVideo.java
@@ -121,8 +121,10 @@ public synchronized ProcessWrapper launchTranscode(
pipe.deleteLater(); // delete the named pipe later; harmless if it isn't created
ProcessWrapper mkfifo_process = pipe.getPipeProcess();
- // Start the process as early as possible
- mkfifo_process.runInNewThread();
+ // It can take a long time for Windows to create a named pipe (and
+ // mkfifo can be slow if /tmp isn't memory-mapped), so run this in
+ // the current thread.
+ mkfifo_process.runInSameThread();
params.input_pipes[0] = pipe;
View
8 src/main/java/net/pms/encoders/MEncoderVideo.java
@@ -2092,11 +2092,11 @@ public ProcessWrapper launchTranscode(
if (!directpipe) {
ProcessWrapper mkfifo_process = pipe.getPipeProcess();
pw.attachProcess(mkfifo_process);
- mkfifo_process.runInNewThread();
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) { }
+ // It can take a long time for Windows to create a named pipe (and
+ // mkfifo can be slow if /tmp isn't memory-mapped), so run this in
+ // the current thread.
+ mkfifo_process.runInSameThread();
pipe.deleteLater();
}
View
9 src/main/java/net/pms/encoders/MEncoderWebVideo.java
@@ -118,16 +118,17 @@ public ProcessWrapper launchTranscode(
ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, params);
pw.attachProcess(mkfifo_process);
- mkfifo_process.runInNewThread();
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) { }
+ // It can take a long time for Windows to create a named pipe (and
+ // mkfifo can be slow if /tmp isn't memory-mapped), so run this in the
+ // current thread.
+ mkfifo_process.runInSameThread();
pipe.deleteLater();
pw.runInNewThread();
+ // Not sure what good this 50ms wait will do for the calling method.
try {
Thread.sleep(50);
} catch (InterruptedException e) { }
View
4 src/main/java/net/pms/io/InternalJavaProcessImpl.java
@@ -31,6 +31,10 @@ public void runInNewThread() {
}
@Override
+ public void runInSameThread() {
+ }
+
+ @Override
public boolean isReadyToStop() {
return false;
}
View
21 src/main/java/net/pms/io/PipeIPCProcess.java
@@ -144,15 +144,36 @@ public void runInNewThread() {
if (!Platform.isWindows()) {
mkin.getPipeProcess().runInNewThread();
mkout.getPipeProcess().runInNewThread();
+
+ // Allow the threads some time to do their work before
+ // starting the main thread
try {
Thread.sleep(150);
} catch (InterruptedException e) {
}
}
+
start();
}
@Override
+ public void runInSameThread() {
+ if (!Platform.isWindows()) {
+ mkin.getPipeProcess().runInNewThread();
+ mkout.getPipeProcess().runInNewThread();
+
+ // Allow the threads some time to do their work before
+ // running the main thread
+ try {
+ Thread.sleep(150);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ run();
+ }
+
+ @Override
public boolean isReadyToStop() {
return false;
}
View
5 src/main/java/net/pms/io/PipeProcess.java
@@ -26,6 +26,11 @@
import java.io.*;
+/**
+ * Process to create a platform specific communications pipe that provides
+ * an input stream and output stream. Other processes can then transmit
+ * content via this pipe.
+ */
public class PipeProcess {
private static final Logger logger = LoggerFactory.getLogger(PipeProcess.class);
private static final PmsConfiguration configuration = PMS.getConfiguration();
View
34 src/main/java/net/pms/io/ProcessWrapper.java
@@ -22,9 +22,43 @@
import java.io.InputStream;
import java.util.List;
+/**
+ * Wrapper for executing a command line process while keeping an eye on it from PMS.
+ */
public interface ProcessWrapper extends UnusedProcess {
+ /**
+ * Retrieves the input stream generated by the command line process.
+ *
+ * @param seek Number of bytes to skip in the input stream.
+ * @return The input stream coming from the process.
+ * @throws IOException
+ */
public InputStream getInputStream(long seek) throws IOException;
+
public List<String> getResults();
+
+ /**
+ * Returns whether or not there still is an underlying process to destroy.
+ * Will return <code>true</code> if the underlying process has been
+ * destroyed already.
+ *
+ * @return <code>true</code> if the process has already been destroyed,
+ * <code>false</code> otherwise.
+ */
public boolean isDestroyed();
+
+ /**
+ * Starts the underlying command line process in a new thread. This means
+ * that the process will run in parallel with the current thread and that
+ * the current thread will not be blocked by its execution.
+ */
public void runInNewThread();
+
+ /**
+ * Starts the underlying command line process in the same thread as the
+ * current thread. This means that the current thread will block until
+ * the execution of the process is finished.
+ */
+ public void runInSameThread();
+
}
View
4 src/main/java/net/pms/io/ProcessWrapperLiteImpl.java
@@ -51,6 +51,10 @@ public void runInNewThread() {
}
@Override
+ public void runInSameThread() {
+ }
+
+ @Override
public boolean isReadyToStop() {
return false;
}
View
6 src/main/java/net/pms/io/WindowsNamedPipe.java
@@ -126,6 +126,12 @@ public boolean isDestroyed() {
@Override
public void runInNewThread() {
+ // Constructor already called start(), do nothing
+ }
+
+ @Override
+ public void runInSameThread() {
+ // Constructor already called start(), do nothing
}
@Override

0 comments on commit 18edeaf

Please sign in to comment.
Something went wrong with that request. Please try again.