olamy commented on code in PR #1799:
URL: https://github.com/apache/maven-resolver/pull/1799#discussion_r2827019807


##########
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultTrackingFileManager.java:
##########
@@ -161,9 +161,19 @@ private FileLock fileLock(FileChannel channel, boolean 
shared) throws IOExceptio
             try {
                 lock = channel.lock(0, Long.MAX_VALUE, shared);
                 break;
-            } catch (OverlappingFileLockException e) {
+            } catch (OverlappingFileLockException | IOException e) {
+                // For Unix process sun.nio.ch.UnixFileDispatcherImpl.lock0() 
is a native method that can throw
+                // IOException
+                // with message "Resource deadlock avoided"
+                // the system call level is involving fcntl() or flock()
+                // If the kernel detects that granting the lock would result 
in a deadlock
+                // (where two processes are waiting for each other to release 
locks which can happen when two processes
+                // are trying to lock the same file),
+                // it returns an EDEADLK error, which Java throws as an 
IOException.

Review Comment:
   Read the message "Resource deadlock avoided" which means the deadlock has 
not happened yet 
   And this the key point, EDEADLK prevents the deadlock rather than reporting 
one that already exists.
   When the kernel returns EDEADLK, it means he refused to grant the lock and 
returns immediately, the calling process is NOT blocked. The other process 
(which is blocked waiting) can now proceed because the cycle no longer exists. 
It completes its work, releases its locks, and when we retry after the 50ms 
sleep, the contention is resolved.
   It looks this deadlock detection is known to eventually produce false 
positives [1] as it's a bit conservative. So the retry simply succeeds 
immediately.
   Maybe adding `e.getMessage().contains("Resource deadlock avoided")` would be 
more precise, so we don't accidentally swallow unrelated IOExceptions during 
the lock attempt. I can add that filter.
   
   
   Here the sequence:
   1. Process A locks tracking file X, then tries to lock tracking file Y
   2. Process B locks tracking file Y, then tries to lock tracking file X
   3. Kernel detects the circular dependency on Process B's attempt -> returns 
EDEADLK to B
   4. Process A is now unblocked (no circular wait) -> completes -> releases 
both locks
   5. Process B retries after 50ms -> succeeds
    
   
   
   [1] https://man7.org/linux/man-pages/man2/F_SETLK.2const.html section Bugs 
Deadlock detection 
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to