Skip to content

Commit

Permalink
FSevents: Support for unscheduling deleted watch
Browse files Browse the repository at this point in the history
* Apply BoboTiG's test patch
* Make the fixture produce a started observer
* Get the exception to come out of the right place.
* If there is no run loop, skip this
  • Loading branch information
exarkun authored and BoboTiG committed Mar 20, 2019
1 parent 9852970 commit 6ba82ac
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/watchdog_fsevents.c
Expand Up @@ -498,18 +498,24 @@ watchdog_stop(PyObject *self, PyObject *emitter_thread)
{
UNUSED(self);
PyObject *value = PyDict_GetItem(thread_to_run_loop, emitter_thread);
if (G_IS_NULL(value)) {
goto success;
}

#if PY_MAJOR_VERSION >= 3
CFRunLoopRef run_loop_ref = PyCapsule_GetPointer(value, NULL);
#else
CFRunLoopRef run_loop_ref = PyCObject_AsVoidPtr(value);
#endif
G_RETURN_NULL_IF(PyErr_Occurred());

/* Stop the run loop. */
if (G_IS_NOT_NULL(run_loop_ref))
{
CFRunLoopStop(run_loop_ref);
}

success:
Py_INCREF(Py_None);
return Py_None;
}
Expand Down
37 changes: 37 additions & 0 deletions tests/test_fsevents.py
Expand Up @@ -8,8 +8,11 @@

import logging
import os
import time
from functools import partial
from os import mkdir, rmdir

from watchdog.observers import Observer
from watchdog.observers.api import ObservedWatch
from watchdog.observers.fsevents import FSEventsEmitter

Expand Down Expand Up @@ -41,6 +44,18 @@ def start_watching(path=None, use_full_emitter=False):
emitter.start()


@pytest.fixture
def observer():
obs = Observer()
obs.start()
yield obs
obs.stop()
try:
obs.join()
except RuntimeError:
pass


def test_remove_watch_twice():
"""
ValueError: PyCapsule_GetPointer called with invalid PyCapsule object
Expand All @@ -63,3 +78,25 @@ def on_thread_stop(self):
emitter.stop()
# This is allowed to call several times .stop()
emitter.stop()


def test_unschedule_removed_folder(observer):
"""
TypeError: PyCObject_AsVoidPtr called with null pointer
The above exception was the direct cause of the following exception:
def on_thread_stop(self):
if self.watch:
_fsevents.remove_watch(self.watch)
E SystemError: <built-in function stop> returned a result with an error set
(FSEvents.framework) FSEventStreamStop(): failed assertion 'streamRef != NULL'
(FSEvents.framework) FSEventStreamInvalidate(): failed assertion 'streamRef != NULL'
(FSEvents.framework) FSEventStreamRelease(): failed assertion 'streamRef != NULL'
"""
a = p("a")
mkdir(a)
w = observer.schedule(event_queue, a, recursive=False)
rmdir(a)
time.sleep(0.1)
observer.unschedule(w)

0 comments on commit 6ba82ac

Please sign in to comment.