LinuxUSBDevice.abortTransfers() can fail with "Invalid argument (error code: 22)".
The reason seems to be a concurrency issue:
Thread 1: The first thread calls LinuxUSBDevice.abortTransfers(), which requires the lock on the LinuxAsyncTask instance.
Thread 2: At the same time, the transfer has been completed or cancelled by the device. The LinuxAsyncTask just reaped the URB and now wants to acquire the lock on itself.
Since the URB was already reaped (thread 2), discarding it (thread 1) will fail.
Output:
Exception in thread "main" java.util.concurrent.CompletionException: net.codecrete.usb.linux.LinuxUSBException: failed to cancel transfer. Invalid argument (error code: 22)
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1807)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796)
at java.base/java.util.concurrent.ForkJoinTask.doExec$$$capture(ForkJoinTask.java:387)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
Caused by: net.codecrete.usb.linux.LinuxUSBException: failed to cancel transfer. Invalid argument (error code: 22)
at net.codecrete.usb.linux.LinuxUSBException.throwException(LinuxUSBException.java:48)
at net.codecrete.usb.linux.LinuxUSBException.throwLastError(LinuxUSBException.java:74)
at net.codecrete.usb.linux.LinuxAsyncTask.abortTransfers(LinuxAsyncTask.java:301)
at net.codecrete.usb.linux.LinuxUSBDevice.abortTransfers(LinuxUSBDevice.java:323)
at net.codecrete.usb.sample.LogicAnalyzer.stopAcquisition(LogicAnalyzer.java:231)
at net.codecrete.usb.sample.LogicAnalyzer.detectBufferOverrun(LogicAnalyzer.java:246)
at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run$$$capture(CompletableFuture.java:1804)
... 8 more
LinuxUSBDevice.abortTransfers()
can fail with "Invalid argument (error code: 22)".The reason seems to be a concurrency issue:
LinuxUSBDevice.abortTransfers()
, which requires the lock on theLinuxAsyncTask
instance.LinuxAsyncTask
just reaped the URB and now wants to acquire the lock on itself.Since the URB was already reaped (thread 2), discarding it (thread 1) will fail.
Output: