$OpenBSD: patch-canto_process_py,v 1.1 2011/03/13 09:36:24 dcoppa Exp $ Fix a crash reported by a user on the #canto irc channel. Patch by Jack Miller (upstream developer) http://codezen.org/cgi-bin/gitweb.cgi?p=canto.git;a=commit;h=e5a4b15b0ddcab49699ab2293d560966fd9af810 --- canto/process.py.orig Tue Jul 27 19:47:06 2010 +++ canto/process.py Fri Mar 11 10:53:43 2011 @@ -106,6 +106,7 @@ from threading import Thread, Lock from cPickle import dumps, loads import select import signal +import errno import time import sys import os @@ -122,17 +123,41 @@ class Queue(): self.thread = None self.alive = True + self.frag = "" + def _try_parse(self): + if "\0" in self.frag: + idx = self.frag.index("\0") + s, self.frag = self.frag[:idx], self.frag[idx+1:] + return loads(s) + return None + def get(self, block=True, timeout=None): + + # Parse a message out of the remaining fragment. + r = self._try_parse() + if r: + return r + ready = self.poll.poll(timeout) - for fd, event in ready: - l = os.read(self.recvpipe, 1) - while l[-1] != " ": - l += os.read(self.recvpipe, 1) - l = int(l) + if not ready: + raise Exception - s = os.read(self.recvpipe, l) - return loads(s) + while True: + try: + self.frag += os.read(self.recvpipe, 1024) + r = self._try_parse() + if r: + return r + except OSError, e: + if e.errno == errno.EINTR: + continue + raise + + if block and timeout == None: + continue + break + raise Exception def feed_pipe(self): @@ -145,9 +170,14 @@ class Queue(): self.objlist = self.objlist[1:] self.objlock.release() - s = dumps(obj) - l = len(s) - os.write(self.sendpipe, "%d %s" % (l, s)) + s = dumps(obj) + "\0" + while s: + try: + written = os.write(self.sendpipe, s) + s = s[written:] + except OSError, e: + if e.errno != errno.EINTR: + raise def put(self, obj): if not self.thread: