"Device busy" When Reopening Serial Port

Any help much appreciated. I am a Java developer, not a Solaris adept. I'm having an issue reopening serial port with the Java app I am developing.

I develop in Windows and deploy the app on Solaris 10 (Sunfire X4170 with Xeon.) On the target machine my app uses the two serial ports /dev/cua/comf1a and /dev/cua/comf1b. If a port cable is unplugged my app detects this (by heartbeats failing to be acknowledged) and closes and then reopens the port. There is no issue in Windows; the app can close and open the port again. But on Solaris, although the app has no trouble opening ports at launch, I get "Device busy" when the app tries to reopen the port, having closed it. I can then shut down and quickly restart the app, and it has no issue opening the ports again on restart. I am sure I am not keeping any ties between the app and the closed port; I am closing input streams and output streams. And there is no issue in Windows. So I think this is an OS-level issue. I have tried making the app wait 15 minutes after closing and before reopening; this doesn't help. I'm wondering whether Solaris has marked the port as in use by the app for the duration of the run of the app so that the port may be closed but not reopened, even by the same app itself.

Thank you for any help you can give me with this.

When it says 'device busy' it generally means so. Try using a utility like lsof to see what's holding it open.

1 Like

Thanks. I'll download that utility try it tomorrow morning.

Another possibility is the device not asserting a hardware control line when the serial port is set for CTS/RTS hardware handshaking, which could prevent the port from opening, I think.

1 Like

Thank you. I can only vaguely understand that. Please excuse my ignorance here. I will investigate that. If it is so, is there a remedy?

also, kindly check if the port opened by your app, has a lock file created ?

1 Like

As far as I know, the X4170 only has a single serial port and I never heard of comf1a/comf1b devices on Solaris. What card and driver are you using ?

---------- Post updated at 22:03 ---------- Previous update was at 21:57 ----------

On Solaris, fuser and pfiles can be used instead of lsof to get that information.

1 Like

Thank you. Will the lock file appear in the same directory as the port?

---------- Post updated at 08:26 PM ---------- Previous update was at 08:21 PM ----------

The machine has two RS 45 jacks used as serial ports. I plug in RS-45-to-serial (9-pin serial) adapter cables. These are indeed the names of the ports. I will find out the card and driver. I'm using the Java Communications library ("Java Comm") as an interface between my Java code and the ports.

I appreciate the help, all.

---------- Post updated at 09:00 PM ---------- Previous update was at 08:26 PM ----------

Instead of downloading lsof, I used fuser.

When the app is running, the command fuser /dev/cua/comf1a yeilds the result:

/dev/cua/comf1a: 18011o

...or a similar string. The name of a thread or a process? When I run the command for /dev/cua/comf1b, I get the same string. So, the same process is associated with both ports. When the app closes one of the ports and continues to run I get the same results. So, closing the port does not stop the port from being associated with this process, if that's what the fuser result means.

When I shut down the app, I get the following result with the command:

/dev/cua/comf1a:

i.e., nothing at all. So, if I'm interpreting fuser correctly, the results are unfortunately that the device is marked busy when the app is running and has opened the device, such that even the app itself cannot open it again.

I do not see any lock file appear in /dev/cua when the app connects to the ports.

I only see one reference to /dev/cua/comf1a (or b) other than mine on the Web: a pdf document on the perle.com site. Perhaps I have an inferior port driver/card? To disallow the very process that is using a device from reopening the device seems unreasonable. Or is there some reconfiguration I can do in Solaris?

---------- Post updated at 09:12 PM ---------- Previous update was at 09:00 PM ----------

Using com.sun.comm.SolarisDriver

I'm not too sure of it myself. Its behavior is fairly system-dependent. All I can suggest is checking the man pages for termios and open on your system.

I just ran a special test. I created a simple, single-thread Java app that just opens, closes, reopens, closes, and for a third time reopens and closes one of the ports, all in a single thread in one block of code. The port was able to be reopened. No issues. No "Device busy".

Therefore, two possibilities arise. One, perhaps I was mistaken in saying that I'm sure that my original application was releasing the port completely upon closing it. But I am sure this isn't so. The Java port object has no handle to my app and my app has no handle to the port object. Two, perhaps the thread which opens a port may reopen it, while other threads may not. Indeed, my app, at launch time, opens the ports in one thread which dies after opening them. The thread which closes and reopens them is a different thread. If Solaris disallows this whereas Windows does not, and no configuration change is possible, then I can perhaps redesign my Java code to accommodate Solaris. I will have to verify this with further testing.

If any of you have any insight on this, I will be very grateful.

Windows is the OS where I'd expect to have problems reopening the port, as it's pointlessly strict about two things having the same device...

Perhaps the garbage-collector hasn't rolled over it yet? Is there a way to explicitly make collection happen?

Thanks for the idea. I suppose the GC is a possibility to consider and it's easy with one simple line of code to ask the GC to collect the garbage (though it isn't deterministic whether it will comply with this request in a timely fashion.) But the references between my Java variables and the port objects, when severed, are severed immediately. The references between my app being immediately gone, "Device busy" should not occur. But I'll try your idea and see.

My next test will be similar to the simple test I mentioned above but will use two threads: one to open the port and one to close and reopen it, thus mocking up my actual app's logic. If this test shows it impossible for the second thread to do the reopen because of "Device busy," then it becomes clear that in Solaris, only the thread that opens the port can reopen it while that thread's containing app is running, other threads being disallowed.

---------- Post updated 12-13-11 at 10:09 AM ---------- Previous update was 12-12-11 at 10:50 AM ----------

I am able to generate a similar issue (PortInUseException) when running on Windows with certain unit tests. So, although the issue varies with OS, it is not isolated to Solaris. Moreover, I have been using Java Comm's library for serial ports. But now that I have switched to the RXTX library (which implements the same classes and method, so one only needs to change the namespace in one's code), then the problem goes away in Windows. I do not have an RXTX library for Solaris x86 yet, so I cannot report that result yet. Also, if I do not add an event listener to the serial port in my code (with SerialPort.addEventListener()), then I do not get the issue with either Java Comm or RXTX. Therefore, it seems that SerialPort.removeEventListener() does not work in JavaComm's implementation but does work in RXTX. This fellow found the issue, too: Day after day

I'll need to use a compilation of RXTX for my Solaris x86 machine now.

I do not see this as an OS issue per se, though it does vary in severity between Solaris and Windows. If I find that RXTX resolves the issue in Windows but not in Solaris then I will report that.

1 Like