from di_mutex import DI_Mutex
display_mutex = DI_Mutex("Display")
try:
display_mutex.acquire()
# do protected mutex access stuff here
finally:
display_mutex.release()
Assume that I want to test if a lock file exists, and if it does - I want to immediately bail, but if it doesn’t I want to create it and continue.
Also assume that the “protected mutex stuff” is the entire blinkin’ script, what do I do?
What I want to accomplish is more like this:
(psudo-code)
import [whatever I need to import]
# Test to see if I am the first instance
if exists (display_lock_file): # does the lock file exist? If so, bail.
print("A previous instance is already running, exiting.")
sys.exit(0)
else:
create(display_lock_file)
# prepare to capture kill signals or ctl-c
create_signal_handler(terminate, interrupt)
(etc. etc. etc.)
# Continue with the script
etc.
etc.
etc.
# special section that receives a terminate or ctl-C
# and gracefully shuts down
when_signal_received(terminate, interrupt):
clear and close the display
remove the lock file.
sys.exit(0)
I’m not sure how to do this with a mutex since all the “protected mutex” stuff is the entire script itself.
Is there a way to do it the way I want? It seems that no matter what I want to do, I have to import either a mutex library, file handling libraries, or “touch”.
lock_file_path = "/var/lock/display.lock"
# Check if this script is already running by looking for the
# "lock file" - if it already exists, the script is already running.
try:
lockfile = open(lock_file_path, "x")
except:
print("A previous exception is already running. exiting.")
sys.exit(0)
else:
lockfile.close() #close the file - it should still remain in place.
# If we got this far, the lock file didn't exist
# and we're the only instance running.
(etc.)
lock_file = "/var/lock/display.lock"
# Check if this script is already running by looking for the
# "lock file" - if it already exists, the script is already running.
try:
lockfile = open(lock_file, "x")
except:
print("A previous instance is already running. exiting.")
sys.exit(0)
else:
lockfile.close()
<snip>
# until some keyboard event is detected
print("Clearing and shutting down display")
# Clear display.
disp.fill(0)
disp.show()
try:
os.remove("/var/lock/display.lock")
except:
print("file doesn't exist. Nothing to do.")
finally:
sys.exit(0)
Mutexes (mutual exclusion locks) are used to synchronize access to shared resources within a single process. They ensure that only one thread can access a critical section of code at a time, preventing race conditions and data corruption.
File locks are used to synchronize access to files across multiple processes. They prevent multiple processes from reading or writing to the same file simultaneously, ensuring data integrity.
The “DI mutex” is a hybrid of these to be both thread-safe and multiprocess-safe.
I think the snippet you show has a some “technical leak paths”. Some are not a problem, but perhaps a system shutdown could leave the lockfile present?
If you mean an abnormal shutdown, absolutely. But then again, that can happen with mutexes too.
The code is designed to capture the shutdown and terminate signals and clean up behind itself.
One thing that I don’t account for - and I am still researching - is what happens if a child process gets the signal before the main process? It’s a known race condition and if the child wins, it throws an exception that forces the parent to abend too.
One of the things I did write is a small sub-utility that does two things:
Resets and clears the display if it’s not already reset and cleared.
Unconditionally removes the lockfile if it’s present.
My “startup_script” that runs as a cron job in the system crontab runs “clearOLED”, (the script I just mentioned), “test_servos”, (that moves the robot’s head to indicate boot-up), and launches the status script.
One additional refinement I made to the status script was to test for, (and replace if necessary), the lock file just in case it was accidentally deleted. This occurs at the end of each cycle via a try, except, finally block with a “pass” in the except part, (the file exists).