[Rxtx] Deadlock in CommPortIdentifier.open with 3 threads ?

Dr. Douglas Lyon lyon at docjava.com
Fri Mar 9 03:58:32 MST 2007


Hi All,
The deadlock issue is one that I have been thinking about
for some time now.
It seems to me that we need a resource manager that enables assignment
to a known process.

The one thing that seems important about serial 
ports is that two applications should not use the 
same serial port at the same time. When this 
happens, it throws an exception.
OK.

The exception is a response to a lock condition that
arises from an unavailable resource.

An abstract implementation (not born of native methods) might
assign a serial port to an application, until the 
application releases it (or is forced to release 
it by some kill mechanism).

Some resources (like a registry) can be reused.
But others, like the serial port,
cannot.

In the case of the serial port, we would like, I think, to
   have the flyweight design pattern
without sharing and with object assignment tracking.
A means of breaking deadlock (like a leasing
mechanism) seems very useful, to me.

My guess is that we can serialize the state of the Parametric Singleton Pattern
(see: http://show.docjava.com:8086/pub/document/jot/v6n3.pdf)
into the Preferences of the System. Preferences.systemRoot() might help
with that. When a resource is checked out, the lease time and owner are
listed. A thread that does this can be killed, but applications outside of Java
are problematic.

There is a compelling problem here. It is not just serial ports.
Sound cards, cameras, microphones, files, tape drives, etc. All are consumed
resources that are assigned to an application (or 
user) and deprive other applications,
or users, from use.

What, if anything, should we do? At present we throw PortInUseExceptions.
Is that it?
Can we do better?
OK, the port is in use. Now what?
Do I have to be root to go remove lock files and kill applications?
Is there a better way?

Thanks!
  - Doug

>I've just struck an issue using rxtx in a multi-threaded environment:
>
>If I have 3 threads trying to open *the same* 
>comm-port I get a deadlock in 
>CommPortIdentifier.open
>If I have just 2, it works fine - I get a 
>PortInUseException which is nice and I can 
>handle it.
>
>The 3 thread->deadlock thing is causing me issues.
>(Sample code below).
>
>This is from the java thread-dump
>
>Found one Java-level deadlock:
>=============================
>"Thread-2":
>   waiting to lock monitor 0x0003e9ec (object 0x240b08e8, a java.lang.Object),
>   which is held by "Thread-1"
>"Thread-1":
>   waiting to lock monitor 0x0003e9cc (object 
>0x2450e108, a gnu.io.CommPortIdentifier ),
>   which is held by "Thread-2"
>
>Java stack information for the threads listed above:
>===================================================
>"Thread-2":
>         at gnu.io.CommPortIdentifier.open (CommPortIdentifier.java:329)
>         - waiting to lock <0x240b08e8> (a java.lang.Object)
>         - locked <0x2450e108> (a gnu.io.CommPortIdentifier)
>         at OpenThread.run(RXTXLockTest.java:42)
>"Thread-1":
>         at java.lang.Object.wait(Native Method)
>         - waiting on <0x2450e108> (a gnu.io.CommPortIdentifier)
>         at gnu.io.CommPortIdentifier.open(CommPortIdentifier.java:332)
>         - locked <0x240b08e8> (a java.lang.Object)
>         - locked <0x2450e108> (a gnu.io.CommPortIdentifier)
>         at OpenThread.run(RXTXLockTest.java:42)
>
>
>(Apart from this, rxtx is working fantastically for us).
>
>I'm thinking I'll have to implement some sort of 
>locking mechanism that *doesn't* use java 
>synchronization to prevent this situation. 
>(Which doesn't sound like a good idea to me).
>
>Any ideas?
>
>Thanks,
>
>Greg Hanna
>
>=============  RXTXLockTest.java ========================================
>
>import gnu.io.CommPort;
>import gnu.io.CommPortIdentifier;
>
>/**
>  * @author Greg Hanna
>  * Minimal code to create a deadlock with rxtx in multithreaded open
>  */
>public class RXTXLockTest {
>     
>     public static void main(String[] args) {
>         try {
>             CommPortIdentifier cpiCom1 = 
>CommPortIdentifier.getPortIdentifier ("COM14");
>             OpenThread t1 = new OpenThread ("  one  ", cpiCom1);
>             OpenThread t2 = new OpenThread ("  two  ", cpiCom1);
>             OpenThread t3 = new OpenThread ("  003  ", cpiCom1);
>             t1.start();
>             t2.start();
>             t3.start();   // comment this out 
>and it runs with (expected) PortInUseException
>         } catch (Exception e) {
>             e.printStackTrace();
>         }
>     }
>}
>
>class OpenThread extends Thread {
>     String name;
>     CommPortIdentifier cpi;
>     CommPort cp;
>     public OpenThread (String name, CommPortIdentifier cpi) {
>         <http://this.name> this.name = name;
>         this.cpi = cpi;
>         System.out.println 
>(System.currentTimeMillis() + name + " thread 
>created");
>     }
>     public void run () {
>         try {
>             System.out.println 
>(System.currentTimeMillis() + name + " opening");
>             cp = cpi.open(name, 2000);
>             System.out.println 
>(System.currentTimeMillis() + name + " opened - 
>sleeping");
>             sleep (2000);  // do the serial comms with the device.
>             System.out.println 
>(System.currentTimeMillis() + name + " slept - 
>closing");
>             cp.close();
>             System.out.println 
>(System.currentTimeMillis() + name + " closed - 
>exiting");
>         } catch (Exception e) {
>             System.out.println ("Error in thread: " + name );
>             e.printStackTrace();
>         }
>     }
>}
>
>
>_______________________________________________
>Rxtx mailing list
>Rxtx at qbang.org
>http://mailman.qbang.org/mailman/listinfo/rxtx





More information about the Rxtx mailing list