processing / processing-video

GStreamer-based video library for Processing
276 stars 130 forks source link

Processing exits without error message on invalid file name with P2D or P3D #220

Open mgunyho opened 1 year ago

mgunyho commented 1 year ago

I was trying to play a video file on Linux and I noticed the following: If the video filename is incorrect (or it's not in the data folder next to the sketch), normally the library gives an error message:

my_sketch.pde:40:0:40:0: RuntimeException: Could not load movie file nonexistent.mp4

which is fine. However, if using the P2D or P3D renderers instead of the default one, there is no error message, Processing just exits "normally". This is the terminal output I get in that case:

Processing video library using bundled GStreamer 1.20.3 (CVS)  
Scanning GStreamer plugins... Done.  
X11Util.Display: Shutdown (JVM shutdown: true, open (no close attempt): 3/3, reusable (open, marked uncloseable): 0, pend  
ing (open in creation order): 3)  
X11Util: Open X11 Display Connections: 3  
X11Util: Open[0]: NamedX11Display[:0, 0x7f01b0747f50, refCount 1, unCloseable false]  
X11Util: Open[1]: NamedX11Display[:0, 0x7f00e8002050, refCount 1, unCloseable false]  
X11Util: Open[2]: NamedX11Display[:0, 0x7f00e8011760, refCount 1, unCloseable false]  
Finished.

The X11 stuff is normal, I get the same terminal output if I just put exit() in my sketch (except for the first two GStreamer-related messages).

Here's a minimal code to reproduce

import processing.video.*;

void setup() {
    // try removing P2D
    size(640, 480, P2D);

    // this should raise an exception if the file doesn't exist
    new Movie(this, "nonexistent.mp4");
}

This is a pretty minor problem but it took me quite a while to figure out.

I initially posted about this on the forum: https://discourse.processing.org/t/linux-processing-exits-when-creating-a-video-movie-if-using-p2d-or-p3d/42627/6

I'm on openSUSE tumbleweed with Processing 4.3 if it makes any difference.

mgunyho commented 1 year ago

Hmm, interestingly it is throwing an exception, but it's not displayed in the terminal output. If I do

try {
    new Movie(this, "nontexistent.mp4");
} catch (RuntimeException ex) {
    println("caught exception", ex);
}

It does get printed to the terminal. So why does changing the renderer change the exception handling of the main Processing process?

mgunyho commented 1 year ago

Seems like the library somehow indeed changes the error handling of the top-level Processing process. I went through different cases, here's the code and output for each.

A: Using the default renderer:

import processing.video.*; 
void setup() { size(640, 480); new Movie(this, "nonexistent.mp4"); }

output:

Processing video library using bundled GStreamer 1.20.3 (CVS)
Scanning GStreamer plugins...
 Done.
test.pde:2:0:2:0: RuntimeException: Could not load movie file nonexistent.mp4

and the Processing window is stuck, it doesn't close, the process doesn't terminate.

B: With P2D (P3D is the same):

import processing.video.*; 
void setup() { size(640, 480, P2D); new Movie(this, "nonexistent.mp4"); }

output:

Processing video library using bundled GStreamer 1.20.3 (CVS)
Scanning GStreamer plugins... Done.
X11Util.Display: Shutdown (JVM shutdown: true, open (no close attempt): 3/3, reusable (open, marked uncloseable): 0, pending (open in creation order): 3)
X11Util: Open X11 Display Connections: 3
X11Util: Open[0]: NamedX11Display[:0, 0x7fd6b075b370, refCount 1, unCloseable false]
X11Util: Open[1]: NamedX11Display[:0, 0x7fd5dc002020, refCount 1, unCloseable false]
X11Util: Open[2]: NamedX11Display[:0, 0x7fd5dc011730, refCount 1, unCloseable false]
Finished.

The Processing window is closed and there's no error message.

C: Using P2D and just exit():

void setup() { size(640, 480, P2D); exit(); }

the output is

X11Util.Display: Shutdown (JVM shutdown: true, open (no close attempt): 3/3, reusable (open, marked uncloseable  
): 0, pending (open in creation order): 3)  
X11Util: Open X11 Display Connections: 3  
X11Util: Open[0]: NamedX11Display[:0, 0x7f1f747138b0, refCount 1, unCloseable false]  
X11Util: Open[1]: NamedX11Display[:0, 0x7f1ea408cf70, refCount 1, unCloseable false]  
X11Util: Open[2]: NamedX11Display[:0, 0x7f1ea40a2c70, refCount 1, unCloseable false]  
Finished.

So basically same as above. This is what confused me: I thought it's exiting normally. With the default renderer, the X11 stuff doesn't appear, just Finished.

D: Default renderer with exception handling:

import processing.video.*; 
void setup() {
    size(640, 480); 
    try { new Movie(this, "nonexistent.mp4"); }
    catch (RuntimeException ex) { println("exception:", ex); }
}

output:

Processing video library using bundled GStreamer 1.20.3 (CVS)  
Scanning GStreamer plugins... Done.  
exception: java.lang.RuntimeException: Could not load movie file nonexistent.mp4

and the window again gets stuck.

E: P2D with exception handling (same code as above but with P2D):

Processing video library using bundled GStreamer 1.20.3 (CVS)  
Scanning GStreamer plugins... Done.  
exception: java.lang.RuntimeException: Could not load movie file nonexistent.mp4  
X11Util.Display: Shutdown (JVM shutdown: true, open (no close attempt): 3/3, reusable (open, marked uncloseable  
): 0, pending (open in creation order): 3)  
X11Util: Open X11 Display Connections: 3  
X11Util: Open[0]: NamedX11Display[:0, 0x7f2e10731890, refCount 1, unCloseable false]  
X11Util: Open[1]: NamedX11Display[:0, 0x7f2d180cc040, refCount 1, unCloseable false]  
X11Util: Open[2]: NamedX11Display[:0, 0x7f2d18043880, refCount 1, unCloseable false]  
Finished.

And the window is closed.

F: If I just throw an exception manually, with the default renderer:

void setup() { size(640, 480); throw new RuntimeException("test"); }

output:

test.pde:1:0:1:0: RuntimeException: test

and the window gets stuck.

G: The same as F but with P2D: the result is the same, the window doesn't close.

So from F and G, we know that changing the renderer doesn't affect the exception handling. But from D and E we know that an exception is thrown for both renderers, but the behavior is different, in one case the window just gets stuck (the "normal" behavior), while in the other there is a graceful shutdown with no error message if the error handling is not done manually.