Skip to content

Commit

Permalink
avoid bad file descriptor shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
altendky committed Jun 9, 2022
1 parent df1574c commit bc5a910
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/watchdog/observers/inotify_c.py
Expand Up @@ -286,6 +286,8 @@ def _recursive_simulate(src_path):
except OSError as e:
if e.errno == errno.EINTR:
continue
elif e.errno == errno.EBADF:
return []
else:
raise
break
Expand Down
25 changes: 23 additions & 2 deletions tests/test_inotify_buffer.py
Expand Up @@ -22,6 +22,7 @@

import os
import random
import time

from watchdog.observers.inotify_buffer import InotifyBuffer

Expand Down Expand Up @@ -132,8 +133,28 @@ def test_unmount_watched_directory_filesystem(p):
assert not inotify.is_alive()


def test_close_should_terminate_thread(p):
inotify = InotifyBuffer(p('').encode(), recursive=True)
def delay_call(function, seconds):
def delayed(*args, **kwargs):
time.sleep(seconds)

return function(*args, **kwargs)

return delayed


class InotifyBufferDelayedRead(InotifyBuffer):
def run(self, *args, **kwargs):
# Introduce a delay to trigger the race condition where the file descriptor is
# closed prior to a read being triggered.
self._inotify.read_events = delay_call(function=self._inotify.read_events, seconds=1)

return super().run(*args, **kwargs)


@pytest.mark.parametrize(argnames="cls", argvalues=[InotifyBuffer, InotifyBufferDelayedRead])
def test_close_should_terminate_thread(p, cls):
inotify = cls(p('').encode(), recursive=True)

assert inotify.is_alive()
inotify.close()
assert not inotify.is_alive()

0 comments on commit bc5a910

Please sign in to comment.