Summary: | [fcntl] F_SETLK returns EDEADLK when it shouldn't - only F_SETLKW and waiting should return EDEADLK | ||
---|---|---|---|
Product: | Base System | Reporter: | Adrian Chadd <adrian> |
Component: | kern | Assignee: | freebsd-bugs (Nobody) <bugs> |
Status: | New --- | ||
Severity: | Affects Only Me | CC: | jilles |
Priority: | --- | ||
Version: | CURRENT | ||
Hardware: | Any | ||
OS: | Any |
Description
Adrian Chadd
2014-07-04 00:50:59 UTC
Here's what I'm trying with: adrian@test3:~/work/freebsd % svn diff stable/10/src/sys/kern/ Index: stable/10/src/sys/kern/kern_lockf.c =================================================================== --- stable/10/src/sys/kern/kern_lockf.c (revision 267627) +++ stable/10/src/sys/kern/kern_lockf.c (working copy) @@ -1425,6 +1425,14 @@ if (lockf_debug & 1) lf_print("lf_setlock: deadlock", lock); #endif + + /* + * If the lock isn't waiting, return EAGAIN + * rather than EDEADLK. + */ + if (((lock->lf_flags & F_WAIT) == 0) && + (error == EDEADLK)) + error = EAGAIN; lf_free_lock(lock); goto out; } .. this seems to fix the problem. .. and I mean F_SETLK. You are right that fcntl(F_SETLK) should not fail with [EDEADLK]; this error is only defined for fcntl(F_SETLKW). A non-blocking locking attempt cannot deadlock. The proposed patch looks wrong, though. The above if ((lock->lf_flags & F_WAIT) == 0 && lock->lf_async_task == NULL) should already catch this case. Perhaps lf_async_task is set incorrectly? I'm still verifying it. I've added some printf()s to see what triggers and where. Is it possible that the initial check will succeed but something will sneak in between that check and actually trying to add the lock? The actual sx lock isn't held for the duration of all of that. I admit I'm not familiar at all in this code. |