diff options
author | Florian Bruhin <git@the-compiler.org> | 2015-09-10 07:38:11 +0200 |
---|---|---|
committer | Florian Bruhin <git@the-compiler.org> | 2015-09-10 07:38:11 +0200 |
commit | 58073fd768424697021ec97c1a789f473c54b401 (patch) | |
tree | b9c059096a81a2d18f680579d49f74f6b3dfe172 | |
parent | 1311e99e7cc2f696fb2813f323fdd30c49ff458e (diff) | |
download | qutebrowser-58073fd768424697021ec97c1a789f473c54b401.tar.gz qutebrowser-58073fd768424697021ec97c1a789f473c54b401.zip |
ipc: Update the atime of the socket all 6h.
See #888.
-rw-r--r-- | qutebrowser/misc/ipc.py | 33 | ||||
-rw-r--r-- | tests/unit/misc/test_ipc.py | 19 |
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: |