Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSError: [Errno9] Bad file descriptor #805

Closed
writeblankspace opened this issue Jun 15, 2021 · 7 comments
Closed

OSError: [Errno9] Bad file descriptor #805

writeblankspace opened this issue Jun 15, 2021 · 7 comments

Comments

@writeblankspace
Copy link

writeblankspace commented Jun 15, 2021

image
I have no idea why this is happening. Looking at the traceback, it looks like a package error.

watch.py

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class Mod_handler(FileSystemEventHandler):
	def on_modified(self, event):
		if(event.src_path == "/database.json"):
			print("Execute your logic here!")
			print("on_modified", event.src_path)

event_handler = Mod_handler()
observer = Observer()
observer.schedule(event_handler, path='/', recursive=False)
observer.start()

def start():
	observer.start()

bot.py

# some unrelated code here
import watch

watch.start()
# some unrelated code here
@BoboTiG BoboTiG changed the title CSError: [Errno9] Bad file descriptor OSError: [Errno9] Bad file descriptor Jun 15, 2021
@dotlambda
Copy link

This also causes a test failure:

==================================== ERRORS ====================================
___________ ERROR at teardown of test_close_should_terminate_thread ____________

recwarn = WarningsRecorder(record=True)

    @pytest.fixture(autouse=True)
    def no_warnings(recwarn):
        """Fail on warning."""

        yield

        warnings = []
        for warning in recwarn:  # pragma: no cover
            message = str(warning.message)
            filename = warning.filename
            if (
                "Not importing directory" in message
                or "Using or importing the ABCs" in message
                or "dns.hash module will be removed in future versions" in message
                or ("eventlet" in filename and "eventlet" in filename)
            ):
                continue
            warnings.append("{w.filename}:{w.lineno} {w.message}".format(w=warning))
>       assert not warnings
E       AssertionError: assert not ['/nix/store/p8mkbxiaqsjqnq53vghf1diy6y3081dn-python3.8-pytest-6.2.4/lib/python3.8/site-packages/_pytest/threadexcepti...ead_events\n    event_buffer = os.read(self._inotify_fd, event_buffer_size)\nOSError: [Errno 9] Bad file descriptor\n']

filename   = '/nix/store/p8mkbxiaqsjqnq53vghf1diy6y3081dn-python3.8-pytest-6.2.4/lib/python3.8/site-packages/_pytest/threadexception.py'
message    = 'Exception in thread Thread-48\n\nTraceback (most recent call last):\n  File "/nix/store/2nhfiak8a30vw67mxksc2kdb69np2...read_events\n    event_buffer = os.read(self._inotify_fd, event_buffer_size)\nOSError: [Errno 9] Bad file descriptor\n'
recwarn    = WarningsRecorder(record=True)
warning    = <warnings.WarningMessage object at 0x7ffff6611eb0>
warnings   = ['/nix/store/p8mkbxiaqsjqnq53vghf1diy6y3081dn-python3.8-pytest-6.2.4/lib/python3.8/site-packages/_pytest/threadexcepti...ead_events\n    event_buffer = os.read(self._inotify_fd, event_buffer_size)\nOSError: [Errno 9] Bad file descriptor\n']

tests/conftest.py:55: AssertionError

@writeblankspace
Copy link
Author

writeblankspace commented Jun 21, 2021

I removed my second observer.start() and put all the code into the start() function:

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

def start():
  class Mod_handler(FileSystemEventHandler):
    def on_modified(self, event):
      if(event.src_path == "/database.json"):
        print("Execute your logic here!")
        print("on_modified", event.src_path)
    
  event_handler = Mod_handler()
  observer = Observer()
  observer.schedule(event_handler, path='/', recursive=False)
  observer.start()

It works now

@BoboTiG
Copy link
Collaborator

BoboTiG commented Jul 29, 2021

@aroberts87
Copy link

Hey all! I'm hitting this issue a lot in my environment. I'm using watchdog to place watches on a directory structure with ~10k folders and ~60M files. The structure is a dumping ground for rsync to move gzip files from our lab equipment for long term storage. I've noticed that rsync creates a temporary file while the transfer is in progress, then either moves or renames the file to the original name. Ex. my_data_file.tar.gz becomes my_data_file.tar.gz.A5B6 on the remote system during transfer, then changed back to my_data_file.tar.gz when the transfer is complete. With several hundred of these events happening every second I see this 'Bad File Descriptor' exception within a few minutes and it kills the Observers I have created.

I'm sharing here to maybe help someone reproduce the issue, or at least give a real world use case that would exacerbate the issue described here.

@altendky
Copy link
Contributor

I don't see any reference here to .stop() or .join() like is done for cleanup in the first example in the readme. Then again, my code didn't have that either. :] I'm trying adding that but since this isn't happening consistently for me it will be awhile before I have confidence this fixed it. Unless it still fails and I know I've failed too... Anyways, it makes sense to need to teardown threads prior to doing cleanup in the main thread.

https://github.com/gorakhargosh/watchdog/tree/72f2eb7203659c11c4f0703c818dcb88fe527e99#example-api-usage

import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = LoggingEventHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    finally:
        observer.stop()
        observer.join()

@altendky
Copy link
Contributor

altendky commented May 30, 2022

While stopping and joining seems like a reasonable thing to be necessary, it alone wasn't sufficient to avoid the bad file descriptor exception. It looks like there's a race condition between shutting down the thread(s) and closing the file descriptor. Even a 10us sleep makes the thread shutdown usually lose. altendky#1 if someone already familiar with the code base has time to add a test and fix, that'd be just awesome! Otherwise, I'll see what I can manage later.

@BoboTiG
Copy link
Collaborator

BoboTiG commented Jun 9, 2022

Fixed with #895.

@BoboTiG BoboTiG closed this as completed Jun 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants