summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <git@the-compiler.org>2015-09-10 07:38:11 +0200
committerFlorian Bruhin <git@the-compiler.org>2015-09-10 07:38:11 +0200
commit58073fd768424697021ec97c1a789f473c54b401 (patch)
treeb9c059096a81a2d18f680579d49f74f6b3dfe172
parent1311e99e7cc2f696fb2813f323fdd30c49ff458e (diff)
downloadqutebrowser-58073fd768424697021ec97c1a789f473c54b401.tar.gz
qutebrowser-58073fd768424697021ec97c1a789f473c54b401.zip
ipc: Update the atime of the socket all 6h.
See #888.
-rw-r--r--qutebrowser/misc/ipc.py33
-rw-r--r--tests/unit/misc/test_ipc.py19
2 files changed, 51 insertions, 1 deletions
diff --git a/qutebrowser/misc/ipc.py b/qutebrowser/misc/ipc.py
index 9bc099791..aa4414b20 100644
--- a/qutebrowser/misc/ipc.py
+++ b/qutebrowser/misc/ipc.py
@@ -27,7 +27,7 @@ import getpass
import binascii
import hashlib
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, Qt
from PyQt5.QtNetwork import QLocalSocket, QLocalServer, QAbstractSocket
import qutebrowser
@@ -38,6 +38,7 @@ from qutebrowser.utils import (log, usertypes, error, objreg, standarddir,
CONNECT_TIMEOUT = 100
WRITE_TIMEOUT = 1000
READ_TIMEOUT = 5000
+ATIME_INTERVAL = 60 * 60 * 6 * 1000 # 6 hours
PROTOCOL_VERSION = 1
@@ -146,6 +147,7 @@ class IPCServer(QObject):
_socketname: The socketname to use.
_socketopts_ok: Set if using setSocketOptions is working with this
OS/Qt version.
+ _atime_timer: Timer to update the atime of the socket regularily.
Signals:
got_args: Emitted when there was an IPC connection and arguments were
@@ -168,11 +170,22 @@ class IPCServer(QObject):
super().__init__(parent)
self.ignored = False
self._socketname = socketname
+
self._timer = usertypes.Timer(self, 'ipc-timeout')
self._timer.setInterval(READ_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.newConnection.connect(self.handle_connection)
+
self._socket = None
self._socketopts_ok = os.name == 'nt' or qtutils.version_check('5.4')
if self._socketopts_ok: # pragma: no cover
@@ -190,6 +203,7 @@ class IPCServer(QObject):
def listen(self):
"""Start listening on self._socketname."""
log.ipc.debug("Listening as {}".format(self._socketname))
+ self._atime_timer.start()
self._remove_server()
ok = self._server.listen(self._socketname)
if not ok:
@@ -330,12 +344,29 @@ class IPCServer(QObject):
log.ipc.error("IPC connection timed out.")
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):
"""Shut down the IPC server cleanly."""
if self._socket is not None:
self._socket.deleteLater()
self._socket = None
self._timer.stop()
+ self._atime_timer.stop()
self._server.close()
self._server.deleteLater()
self._remove_server()
diff --git a/tests/unit/misc/test_ipc.py b/tests/unit/misc/test_ipc.py
index db89d11b2..34d709458 100644
--- a/tests/unit/misc/test_ipc.py
+++ b/tests/unit/misc/test_ipc.py
@@ -324,6 +324,25 @@ class TestListen:
assert file_owner_ok or dir_owner_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: