Add timeout to IPC server.

This commit is contained in:
Florian Bruhin 2014-10-13 22:47:32 +02:00
parent 4617aee317
commit 6b07fd969a

View File

@ -25,12 +25,13 @@ import getpass
from PyQt5.QtCore import pyqtSlot, QObject from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QLocalSocket, QLocalServer from PyQt5.QtNetwork import QLocalSocket, QLocalServer
from qutebrowser.utils import log, objreg from qutebrowser.utils import log, objreg, usertypes
SOCKETNAME = 'qutebrowser-{}'.format(getpass.getuser()) SOCKETNAME = 'qutebrowser-{}'.format(getpass.getuser())
CONNECT_TIMEOUT = 100 CONNECT_TIMEOUT = 100
WRITE_TIMEOUT = 1000 WRITE_TIMEOUT = 1000
READ_TIMEOUT = 5000
class IPCError(Exception): class IPCError(Exception):
@ -46,6 +47,9 @@ class IPCServer(QObject):
"""Start the IPC server and listen to commands.""" """Start the IPC server and listen to commands."""
super().__init__(parent) super().__init__(parent)
self._remove_server() self._remove_server()
self._timer = usertypes.Timer(self, 'ipc-timeout')
self._timer.setInterval(READ_TIMEOUT)
self._timer.timeout.connect(self.on_timeout)
self._server = QLocalServer(self) self._server = QLocalServer(self)
ok = self._server.listen(SOCKETNAME) ok = self._server.listen(SOCKETNAME)
if not ok: if not ok:
@ -65,6 +69,7 @@ class IPCServer(QObject):
@pyqtSlot(int) @pyqtSlot(int)
def on_error(self, error): def on_error(self, error):
"""Convenience method which calls _socket_error on an error.""" """Convenience method which calls _socket_error on an error."""
self._timer.stop()
log.ipc.debug("Socket error {}: {}".format( log.ipc.debug("Socket error {}: {}".format(
self._socket.error(), self._socket.errorString())) self._socket.error(), self._socket.errorString()))
if error != QLocalSocket.PeerClosedError: if error != QLocalSocket.PeerClosedError:
@ -82,6 +87,7 @@ class IPCServer(QObject):
log.ipc.debug("No new connection to handle.") log.ipc.debug("No new connection to handle.")
return return
log.ipc.debug("Client connected.") log.ipc.debug("Client connected.")
self._timer.start()
self._socket = socket self._socket = socket
socket.readyRead.connect(self.on_ready_read) socket.readyRead.connect(self.on_ready_read)
if socket.canReadLine(): if socket.canReadLine():
@ -101,6 +107,7 @@ class IPCServer(QObject):
def on_disconnected(self): def on_disconnected(self):
"""Clean up socket when the client disconnected.""" """Clean up socket when the client disconnected."""
log.ipc.debug("Client disconnected.") log.ipc.debug("Client disconnected.")
self._timer.stop()
self._socket.deleteLater() self._socket.deleteLater()
self._socket = None self._socket = None
# Maybe another connection is waiting. # Maybe another connection is waiting.
@ -113,6 +120,7 @@ class IPCServer(QObject):
# this happened once and I don't know why # this happened once and I don't know why
log.ipc.warn("In on_ready_read with None socket!") log.ipc.warn("In on_ready_read with None socket!")
return return
self._timer.start()
while self._socket.canReadLine(): while self._socket.canReadLine():
data = bytes(self._socket.readLine()) data = bytes(self._socket.readLine())
log.ipc.debug("Read from socket: {}".format(data)) log.ipc.debug("Read from socket: {}".format(data))
@ -131,11 +139,18 @@ class IPCServer(QObject):
app = objreg.get('app') app = objreg.get('app')
app.process_args(args) app.process_args(args)
@pyqtSlot()
def on_timeout(self):
"""Cancel the current connection if it was idle for too long."""
log.ipc.error("IPC connection timed out.")
self._socket.close()
def shutdown(self): def shutdown(self):
"""Shut down the IPC server cleanly.""" """Shut down the IPC server cleanly."""
if self._socket is not None: if self._socket is not None:
self._socket.deleteLater() self._socket.deleteLater()
self._socket = None self._socket = None
self._timer.stop()
self._server.close() self._server.close()
self._server.deleteLater() self._server.deleteLater()
self._remove_server() self._remove_server()