From 08be09ee408f750ff09b61742939b641edff1e68 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Sun, 17 Nov 2013 09:27:55 -0700 Subject: [PATCH] Fixed RemoteGraphicsView on windows - Avoid using authkey on windows; seems to be broken - Included yet another method of accessing shared memory as QImage --- pyqtgraph/multiprocess/processes.py | 22 ++++++++++++++++++---- pyqtgraph/multiprocess/remoteproxy.py | 6 +++--- pyqtgraph/widgets/RemoteGraphicsView.py | 12 +++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/pyqtgraph/multiprocess/processes.py b/pyqtgraph/multiprocess/processes.py index cf802352..16fd6bab 100644 --- a/pyqtgraph/multiprocess/processes.py +++ b/pyqtgraph/multiprocess/processes.py @@ -35,7 +35,7 @@ class Process(RemoteEventHandler): ProxyObject for more information. """ - def __init__(self, name=None, target=None, executable=None, copySysPath=True, debug=False): + def __init__(self, name=None, target=None, executable=None, copySysPath=True, debug=False, timeout=20): """ ============ ============================================================= Arguments: @@ -63,19 +63,23 @@ class Process(RemoteEventHandler): ## random authentication key authkey = os.urandom(20) + + ## Windows seems to have a hard time with hmac + if sys.platform.startswith('win'): + authkey = None + #print "key:", ' '.join([str(ord(x)) for x in authkey]) ## Listen for connection from remote process (and find free port number) port = 10000 while True: try: - ## hmac authentication appears to be broken on windows (says AuthenticationError: digest received was wrong) l = multiprocessing.connection.Listener(('localhost', int(port)), authkey=authkey) break except socket.error as ex: if ex.errno != 98: raise port += 1 - + ## start remote process, instruct it to run target function sysPath = sys.path if copySysPath else None bootstrap = os.path.abspath(os.path.join(os.path.dirname(__file__), 'bootstrap.py')) @@ -111,7 +115,7 @@ class Process(RemoteEventHandler): self.proc.stdin.close() ## open connection for remote process - self.debugMsg('Listening for child process..') + self.debugMsg('Listening for child process on port %d, authkey=%s..' % (port, repr(authkey))) while True: try: conn = l.accept() @@ -140,7 +144,12 @@ class Process(RemoteEventHandler): def startEventLoop(name, port, authkey, ppid, debug=False): + if debug: + import os + print('[%d] connecting to server at port localhost:%d, authkey=%s..' % (os.getpid(), port, repr(authkey))) conn = multiprocessing.connection.Client(('localhost', int(port)), authkey=authkey) + if debug: + print('[%d] connected; starting remote proxy.' % os.getpid()) global HANDLER #ppid = 0 if not hasattr(os, 'getppid') else os.getppid() HANDLER = RemoteEventHandler(conn, name, ppid, debug=debug) @@ -380,7 +389,12 @@ class QtProcess(Process): self.timer.stop() def startQtEventLoop(name, port, authkey, ppid, debug=False): + if debug: + import os + print('[%d] connecting to server at port localhost:%d, authkey=%s..' % (os.getpid(), port, repr(authkey))) conn = multiprocessing.connection.Client(('localhost', int(port)), authkey=authkey) + if debug: + print('[%d] connected; starting remote proxy.' % os.getpid()) from pyqtgraph.Qt import QtGui, QtCore #from PyQt4 import QtGui, QtCore app = QtGui.QApplication.instance() diff --git a/pyqtgraph/multiprocess/remoteproxy.py b/pyqtgraph/multiprocess/remoteproxy.py index 702b10bc..eba42ef3 100644 --- a/pyqtgraph/multiprocess/remoteproxy.py +++ b/pyqtgraph/multiprocess/remoteproxy.py @@ -97,7 +97,6 @@ class RemoteEventHandler(object): after no more events are immediately available. (non-blocking) Returns the number of events processed. """ - self.debugMsg('processRequests:') if self.exited: self.debugMsg(' processRequests: exited already; raise ClosedError.') raise ClosedError() @@ -108,7 +107,7 @@ class RemoteEventHandler(object): self.handleRequest() numProcessed += 1 except ClosedError: - self.debugMsg(' processRequests: got ClosedError from handleRequest; setting exited=True.') + self.debugMsg('processRequests: got ClosedError from handleRequest; setting exited=True.') self.exited = True raise #except IOError as err: ## let handleRequest take care of this. @@ -121,7 +120,8 @@ class RemoteEventHandler(object): print("Error in process %s" % self.name) sys.excepthook(*sys.exc_info()) - self.debugMsg(' processRequests: finished %d requests' % numProcessed) + if numProcessed > 0: + self.debugMsg('processRequests: finished %d requests' % numProcessed) return numProcessed def handleRequest(self): diff --git a/pyqtgraph/widgets/RemoteGraphicsView.py b/pyqtgraph/widgets/RemoteGraphicsView.py index f8bbb6cf..ac29f426 100644 --- a/pyqtgraph/widgets/RemoteGraphicsView.py +++ b/pyqtgraph/widgets/RemoteGraphicsView.py @@ -188,11 +188,16 @@ class Renderer(GraphicsView): self.img = QtGui.QImage(ch, self.width(), self.height(), QtGui.QImage.Format_ARGB32) else: address = ctypes.addressof(ctypes.c_char.from_buffer(self.shm, 0)) + + # different versions of pyqt have different requirements here.. try: self.img = QtGui.QImage(sip.voidptr(address), self.width(), self.height(), QtGui.QImage.Format_ARGB32) except TypeError: - # different versions of pyqt have different requirements here.. - self.img = QtGui.QImage(memoryview(buffer(self.shm)), self.width(), self.height(), QtGui.QImage.Format_ARGB32) + try: + self.img = QtGui.QImage(memoryview(buffer(self.shm)), self.width(), self.height(), QtGui.QImage.Format_ARGB32) + except TypeError: + # Works on PyQt 4.9.6 + self.img = QtGui.QImage(address, self.width(), self.height(), QtGui.QImage.Format_ARGB32) self.img.fill(0xffffffff) p = QtGui.QPainter(self.img) self.render(p, self.viewRect(), self.rect()) @@ -236,6 +241,3 @@ class Renderer(GraphicsView): ev = QtCore.QEvent(QtCore.QEvent.Type(typ)) return GraphicsView.leaveEvent(self, ev) - - -