From 933089eb14e3810e5e431f2d8d05643edaab14d7 Mon Sep 17 00:00:00 2001 From: Florian Best Date: Wed, 27 Jan 2016 18:02:04 +0100 Subject: [PATCH] Fix KeyError if socket is removed in timer The following script demonstrates a KeyError which is caused if a socket which currently has some pending input/output was removed in a notifier timer. The problem is that step() first poll()s, then executes the timers() and then uses the polled FD's. $ cat timer_bug.py import notifier import subprocess notifier.init() fd = None def on_read(sock): print 'on_read' return True def on_timer(): print 'on_timer' notifier.socket_remove(fd) return True p = subprocess.Popen('python -c "import sys; sys.stdin.read()"', shell=True, stdin=subprocess.PIPE) fd = p.stdin.fileno() notifier.socket_add(fd, on_read) notifier.timer_add(0, on_timer) p.communicate('A') notifier.step() $ python timer_bug.py on_timer Traceback (most recent call last): File "timer_bug.py", line 18, in notifier.step() File "/home/git/python-notifier/notifier/nf_generic.py", line 259, in step sock_obj = __sock_objects[ fd ] KeyError: 4 --- notifier/nf_generic.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notifier/nf_generic.py b/notifier/nf_generic.py index b14be10..9eb4ea9 100644 --- a/notifier/nf_generic.py +++ b/notifier/nf_generic.py @@ -255,7 +255,10 @@ def step( sleep = True, external = True ): # handle sockets if fds: for fd, condition in fds: - sock_obj = __sock_objects[ fd ] + try: + sock_obj = __sock_objects[ fd ] + except KeyError: + continue # ignore recently removed socket (by timer in this step() call) # check for closed pipes/sockets if condition in ( select.POLLHUP, select.POLLNVAL ): socket_remove( sock_obj, IO_ALL )