Fazecast / jSerialComm

Platform-independent serial port access for Java
GNU Lesser General Public License v3.0
1.34k stars 287 forks source link

Separate tmpdir across applications #352

Closed yigitpirildak closed 3 years ago

yigitpirildak commented 3 years ago

We've been using the library for quite some time and recently ran into some problems related to the static initialization block inside SerialPort.java.

The issue only occurs if the library is used in multiple applications and they're all started at the same time (Still happens very rarely though, takes a lot of attempts to reproduce the issue).

Here's the stack trace:

Exception in thread "Thread-0" java.lang.ExceptionInInitializerError
   at com.somepackage.SerialConnector.run(SerialConnector.java:58)
Caused by: java.lang.NullPointerException
   at com.fazecast.jSerialComm.SerialPort.deleteDirectory(SerialPort.java:270)
   at com.fazecast.jSerialComm.SerialPort.<clinit>(SerialPort.java:66)

Error is unrecoverable since it happens inside the class initializer, rendering the SerialPort.java useless afterwards.

After looking into the source, we've realized there's a potential race condition to cause listFiles() method used inside deleteDirectory() to throw a NullPointerException. The issue occurs if following happens:

I intentionally added a System property so that it's up to the developer to handle this in case its needed. Didn't want to rely on properties such as "sun.java.command" for a main package name since I'm not sure it's reliable enough to produce a valid directory.

Lastly, adding a null check for path.listFiles() may seem like it would fix this issue, there's still a problematic case where applications delete each others extracted libraries. For example, unless we use separate folder for every application, Application1 may recreate the tmp folder and put its .so file but before it can be loaded, Application2 goes ahead and deletes the directory and everything in it.

I would also appreciate alternative approaches to fix this issue.

Note: I am able to fix the issue by just setting java.io.tmpdir to some other directory for each application, but I'd rather not do that. I think the library itself should support this (would be better if it were seamless) or at least provide guidance/warning if this is not to be merged.

Thanks in advance.