]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll: unlock read lock if write lock fails in readWriteLock
authorqmuntal <quimmuntal@gmail.com>
Fri, 30 Jan 2026 13:26:57 +0000 (14:26 +0100)
committerQuim Muntal <quimmuntal@gmail.com>
Wed, 4 Feb 2026 19:54:32 +0000 (11:54 -0800)
If the write lock acquisition fails, the read lock acquired earlier is
not released, leading to a potential deadlock.

The deadlock shouldn't occur because when the write lock fails, it
indicates that the FD is closing, and no other goroutine should be
holding the read lock. However, better to be safe and release the read
lock in such cases.

Change-Id: If593c36040a97357f835b42bb3133ff1dc55a638
Reviewed-on: https://go-review.googlesource.com/c/go/+/740560
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
src/internal/poll/fd_mutex.go

index f71c7739a1aa6e1a1eb1962264a9e00644b0a90a..aa8f425235aae87b31ce69fde747d4e5b0966d26 100644 (file)
@@ -254,7 +254,11 @@ func (fd *FD) writeUnlock() {
 // readWriteLock adds a reference to fd and locks fd for reading and writing.
 // It returns an error when fd cannot be used for reading and writing.
 func (fd *FD) readWriteLock() error {
-       if !fd.fdmu.rwlock(true) || !fd.fdmu.rwlock(false) {
+       if !fd.fdmu.rwlock(true) {
+               return errClosing(fd.isFile)
+       }
+       if !fd.fdmu.rwlock(false) {
+               fd.fdmu.rwunlock(true) // unlock read lock acquired above
                return errClosing(fd.isFile)
        }
        return nil