parent
1311e99e7c
commit
58073fd768
@ -27,7 +27,7 @@ import getpass
|
|||||||
import binascii
|
import binascii
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt
|
||||||
from PyQt5.QtNetwork import QLocalSocket, QLocalServer, QAbstractSocket
|
from PyQt5.QtNetwork import QLocalSocket, QLocalServer, QAbstractSocket
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
@ -38,6 +38,7 @@ from qutebrowser.utils import (log, usertypes, error, objreg, standarddir,
|
|||||||
CONNECT_TIMEOUT = 100
|
CONNECT_TIMEOUT = 100
|
||||||
WRITE_TIMEOUT = 1000
|
WRITE_TIMEOUT = 1000
|
||||||
READ_TIMEOUT = 5000
|
READ_TIMEOUT = 5000
|
||||||
|
ATIME_INTERVAL = 60 * 60 * 6 * 1000 # 6 hours
|
||||||
PROTOCOL_VERSION = 1
|
PROTOCOL_VERSION = 1
|
||||||
|
|
||||||
|
|
||||||
@ -146,6 +147,7 @@ class IPCServer(QObject):
|
|||||||
_socketname: The socketname to use.
|
_socketname: The socketname to use.
|
||||||
_socketopts_ok: Set if using setSocketOptions is working with this
|
_socketopts_ok: Set if using setSocketOptions is working with this
|
||||||
OS/Qt version.
|
OS/Qt version.
|
||||||
|
_atime_timer: Timer to update the atime of the socket regularily.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
got_args: Emitted when there was an IPC connection and arguments were
|
got_args: Emitted when there was an IPC connection and arguments were
|
||||||
@ -168,11 +170,22 @@ class IPCServer(QObject):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.ignored = False
|
self.ignored = False
|
||||||
self._socketname = socketname
|
self._socketname = socketname
|
||||||
|
|
||||||
self._timer = usertypes.Timer(self, 'ipc-timeout')
|
self._timer = usertypes.Timer(self, 'ipc-timeout')
|
||||||
self._timer.setInterval(READ_TIMEOUT)
|
self._timer.setInterval(READ_TIMEOUT)
|
||||||
self._timer.timeout.connect(self.on_timeout)
|
self._timer.timeout.connect(self.on_timeout)
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
self._atime_timer = None
|
||||||
|
else:
|
||||||
|
self._atime_timer = usertypes.Timer(self, 'ipc-atime')
|
||||||
|
self._atime_timer.setInterval(READ_TIMEOUT)
|
||||||
|
self._atime_timer.timeout.connect(self.update_atime)
|
||||||
|
self._atime_timer.setTimerType(Qt.VeryCoarseTimer)
|
||||||
|
|
||||||
self._server = QLocalServer(self)
|
self._server = QLocalServer(self)
|
||||||
self._server.newConnection.connect(self.handle_connection)
|
self._server.newConnection.connect(self.handle_connection)
|
||||||
|
|
||||||
self._socket = None
|
self._socket = None
|
||||||
self._socketopts_ok = os.name == 'nt' or qtutils.version_check('5.4')
|
self._socketopts_ok = os.name == 'nt' or qtutils.version_check('5.4')
|
||||||
if self._socketopts_ok: # pragma: no cover
|
if self._socketopts_ok: # pragma: no cover
|
||||||
@ -190,6 +203,7 @@ class IPCServer(QObject):
|
|||||||
def listen(self):
|
def listen(self):
|
||||||
"""Start listening on self._socketname."""
|
"""Start listening on self._socketname."""
|
||||||
log.ipc.debug("Listening as {}".format(self._socketname))
|
log.ipc.debug("Listening as {}".format(self._socketname))
|
||||||
|
self._atime_timer.start()
|
||||||
self._remove_server()
|
self._remove_server()
|
||||||
ok = self._server.listen(self._socketname)
|
ok = self._server.listen(self._socketname)
|
||||||
if not ok:
|
if not ok:
|
||||||
@ -330,12 +344,29 @@ class IPCServer(QObject):
|
|||||||
log.ipc.error("IPC connection timed out.")
|
log.ipc.error("IPC connection timed out.")
|
||||||
self._socket.close()
|
self._socket.close()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def update_atime(self):
|
||||||
|
"""Update the atime of the socket file all few hours.
|
||||||
|
|
||||||
|
From the XDG basedir spec:
|
||||||
|
|
||||||
|
To ensure that your files are not removed, they should have their
|
||||||
|
access time timestamp modified at least once every 6 hours of monotonic
|
||||||
|
time or the 'sticky' bit should be set on the file.
|
||||||
|
"""
|
||||||
|
path = self._server.fullServerName()
|
||||||
|
if not path:
|
||||||
|
log.ipc.error("In update_atime with no server path!")
|
||||||
|
return
|
||||||
|
os.utime(path)
|
||||||
|
|
||||||
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._timer.stop()
|
||||||
|
self._atime_timer.stop()
|
||||||
self._server.close()
|
self._server.close()
|
||||||
self._server.deleteLater()
|
self._server.deleteLater()
|
||||||
self._remove_server()
|
self._remove_server()
|
||||||
|
@ -324,6 +324,25 @@ class TestListen:
|
|||||||
assert file_owner_ok or dir_owner_ok
|
assert file_owner_ok or dir_owner_ok
|
||||||
assert file_mode_ok or dir_mode_ok
|
assert file_mode_ok or dir_mode_ok
|
||||||
|
|
||||||
|
@pytest.mark.posix
|
||||||
|
def test_atime_update(self, qtbot, ipc_server):
|
||||||
|
ipc_server._atime_timer.setInterval(500) # We don't want to wait 6h
|
||||||
|
ipc_server.listen()
|
||||||
|
old_atime = os.stat(ipc_server._server.fullServerName()).st_atime_ns
|
||||||
|
|
||||||
|
with qtbot.waitSignal(ipc_server._atime_timer.timeout, timeout=2000,
|
||||||
|
raising=True):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Make sure the timer is not singleShot
|
||||||
|
with qtbot.waitSignal(ipc_server._atime_timer.timeout, timeout=2000,
|
||||||
|
raising=True):
|
||||||
|
pass
|
||||||
|
|
||||||
|
new_atime = os.stat(ipc_server._server.fullServerName()).st_atime_ns
|
||||||
|
|
||||||
|
assert old_atime != new_atime
|
||||||
|
|
||||||
|
|
||||||
class TestOnError:
|
class TestOnError:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user