Comments (11)
How to repeat the bug on FreeBSD:
mkdir -p /tmp/test/1
cat > /tmp/main.c << EOF
#include <sys/inotify.h>
int main() {
int inotify_d = inotify_init();
inotify_add_watch(inotify_d, "/tmp/test", 0x2000fce);
return inotify_add_watch(inotify_d, "/tmp/test/1", 0x2000fce);
}
EOF
gcc49 -linotify /tmp/main.c -o /tmp/test.bin
/tmp/test.bin
from libinotify-kqueue.
It's just a race conditions. There's no bug if I insert sleep(3)
between inotify_add_watch()
calls in the example above.
from libinotify-kqueue.
Thanks for report. Looks like that busy wait is really busy. Do tests run ok on your system? (make test
).
In any case, could you please comment out line 16 in barriers.h
(#define WITHOUT_BARRIERS
), rebuild the library and try to reproduce it again?
from libinotify-kqueue.
make test (for recent git version of libinotify):
[root@freebsd10 /tmp/libinotify-kqueue]# make test
Running test suite...
..............xx.......xx.....x....xx...xx...xx.x.............
In test "Start-stop test":
failed: all produced events are registered after resume
In test "Start-stop directory":
failed: receive all events on a resumed watch
failed: receive events for a same file from both watches (sometimes this test fails event on Linux, at least on 2.6.39)
In test "Update watch flags":
failed: receive notifications on modify with flags = IN_ATTRIB | IN_MODIFY
failed: do not receive notifications on touch with flags = IN_MODIFY
In test "Update directory flags":
failed: receive modify notifications for files in a directory with IN_MODIFY
In test "Open/close notifications":
failed: receive IN_OPEN on cat
failed: receive IN_CLOSE_NOWRITE on cat
failed: receive IN_OPEN on ls
failed: receive IN_CLOSE_NOWRITE on ls
failed: receive IN_OPEN on modify
failed: receive IN_CLOSE_WRITE on modify
--------------------
Run: 62
Passed: 50
Failed: 12
make test (from ports):
[root@freebsd10 /usr/ports/devel/libinotify/work/dmatveev-libinotify-kqueue-2a0d601]# make test
gcc49 -O2 -pipe -I/usr/ports/devel/libinotify/work/dmatveev-libinotify-kqueue-2a0d601 -DNDEBUG -pthread -std=gnu99 -fstack-protector -linotify -L/usr/local/lib test.c -o test
[root@freebsd10 /usr/ports/devel/libinotify/work/dmatveev-libinotify-kqueue-2a0d601]# make test
`test' is up to date.
[root@freebsd10 /usr/ports/devel/libinotify/work/dmatveev-libinotify-kqueue-2a0d601]# ./test
Watching the current directory
In any case, could you please comment out line 16 in
barriers.h
(#define WITHOUT_BARRIERS
), rebuild the library and try to reproduce it again?
Works :)
[root@freebsd10 /usr/ports/devel/libinotify/work/dmatveev-libinotify-kqueue-2a0d601]# time /tmp/test.bin
real 0m0.003s
user 0m0.000s
sys 0m0.008s
from libinotify-kqueue.
Tests are made on separate virtual machine, so I can share it with you if you wish)
from libinotify-kqueue.
The race condition appears due to next problem:
OS saves CPU using rare context switching, so there may be no context switch between "--impl->sleeping" and "++impl->sleeping". And that's how the deadlock appears with infinite "while (impl->sleeping != 0);" and "pthread_cond_wait()".
It's required to allow the loop ("while (impl->sleeping != 0)") to end despite this. I think I can prepare a patch.
Sorry for my English. I hope I make myself clear.
from libinotify-kqueue.
The patch is ready.
from libinotify-kqueue.
Confirmed on NetBSD
from libinotify-kqueue.
The issue was in the ik_barrier_impl_wait
function. In our scenario, we had two threads -- a main thread and a kqueue worker thread. Barriers are used to synchronize both threads when passing commands (add watch, rm watch) from main to worker.
Main Worker
---- ------
inotify_add_watch() kevent()
worker_cmd_add() :
write(fd, "*") ---------> kevent() returns
worker_cmd_wait() process_command()
ik_barrier_wait() worker_cmd_wait()
[1] ik_barrier_wait()
[2]
At [1]
, the main thread serializes the command data in a special structure, sends a notification to the worker thread, and blocks on a barrier. The worker thread wakes up, processes the command, passes back result, and also checks in on a barrier [2]
.
Having a busy wait to ensure all threads release barrier's locks was a bad idea. In our scenario, the main thread left the barrier, then destroyed it, and then initialized with new data again (in the subsequent call to inotify_add_watch()
) BEFORE the worker thread started to busy wait on the barrier.
In other words (c
is the counter):
Thread A Thread B
-------- --------
Enter(c=0) :
Sleep Enter(c=1)
Wake up <-- Signal
Leave :
Destroy :
Init(c=0) :
Enter(c=1) :
Busy wait(c=1)
from libinotify-kqueue.
I'll test the new version for my case tomorrow :)
from libinotify-kqueue.
Thanks. The new version doesn't hang. :)
from libinotify-kqueue.
Related Issues (18)
- libinotify open() considerations HOT 5
- Lost deletion events HOT 2
- The deletion events are not provided in time HOT 16
- Propagate changes from #12 to gio-kqueue
- use-after-free in worker_sets_extend/worker_update_flags HOT 2
- wulf7/libinotify-kqueue integration HOT 3
- Crashes reported for 271ef97 HOT 10
- [suggestion] Implement command line interface like 'inotifywait' in linux HOT 4
- Build failure: Missing file barriers.c
- incrond fails at monitoring directories HOT 10
- #include <sys/tree.h> is missing on FreeBSD HOT 8
- Test results: FreeBSD-10.2 HOT 6
- Question: Only watch directories HOT 6
- Mistakenly close down fd 0 upon watch failure HOT 4
- Where is the documentation? HOT 2
- "make test" sometimes gets killed with SIGPIPE HOT 3
- Doesn't set IN_ISDIR if new directory is created HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from libinotify-kqueue.