Skip to content

Commit

Permalink
Reset Mutex (Issue 2429) (#2460)
Browse files Browse the repository at this point in the history
Force the Mu-tex to reset if it's being held by a zombie process

If a process crashes hard before releasing the Mu-tex then a new process won't be able to start. (This is only likely to happen on Linux which doesn't automatically release the shared memory we use to implement the mutex).

This PR always attaches and detaches from the shared memory before checking whether or not it can attach and read the contents. This is enough to take control of the mutex from the zombie process
  • Loading branch information
tjguk authored Sep 30, 2023
1 parent 9a32b33 commit 27bfb77
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ coverage: clean
export LANG=en_GB.utf8
pytest -v --random-order --cov-config setup.cfg --cov-report term-missing --cov=mu tests/

tidy:
tidy:
python make.py tidy

black:
Expand Down
11 changes: 10 additions & 1 deletion mu/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,16 @@ def __exit__(self, *args, **kwargs):
self._shared_memory.unlock()

def acquire(self):
#
# The attach-detach dance is a shim from
# https://stackoverflow.com/questions/42549904/qsharedmemory-is-not-getting-deleted-on-application-crash
# If the existing shared memory is not held by any active application
# (eg because an appimage has hard-crashed) then it will be released
# If the memory is held by an active application it will have no effect
#
self._shared_memory.attach()
self._shared_memory.detach()

if self._shared_memory.attach():
pid = struct.unpack("q", self._shared_memory.data()[:8])
raise MutexError("MUTEX: Mu is already running with pid %d" % pid)
Expand Down Expand Up @@ -354,7 +364,6 @@ def run():
logging.info("Platform: {}".format(platform.platform()))
logging.info("Python path: {}".format(sys.path))
logging.info("Language code: {}".format(i18n.language_code))

setup_exception_handler()
check_only_running_once()

Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ exclude =
./.venv*/
./env/
./.env/
./local-scripts/
max-line-length = 88

[coverage:run]
Expand Down

0 comments on commit 27bfb77

Please sign in to comment.