Issue
I have a Makefile with a target that executes multiple system-wide operations (e.g. installing packages), so I want to lock the target in a way that other make processes will wait on that target, thus preventing parallel execution.
I tried using flock as explained in this answer, but I think the particularities of makefiles are getting in the way.
This is what I have right now:
LOCKFILE=/var/lock/makefile.lock
LOCKFD=200
mytarget:
# make sure to release the lock in any case
eval "exec $(LOCKFD)>$(LOCKFILE)"; trap "flock -xn $(LOCKFD) && rm -f $(LOCKFILE)" EXIT
# get exclusive waiting lock
flock -x $(LOCKFD)
[regular target operations...]
# release lock and delete the lock file
flock -u $(LOCKFD); flock -xn $(LOCKFD) && rm -f $(LOCKFILE)
It fails with this error, because the file descriptor 200 is not properly set:
$ make mytarget
# make sure to release the lock in any case
eval "exec 200>/var/lock/makefile.lock"; trap "flock -xn 200 && rm -f /var/lock/makefile.lock" EXIT
# get exclusive waiting lock
flock -x 200
flock: 200: Bad file descriptor
Makefile:57: recipe for target 'mytarget' failed
There has to be something wrong with the eval
definition, but I don't see what.
Solution
Make runs every command line in a new shell. I guess your fd is gone after eval
. You can use a single command line and separate commands with ";". If you want to split the command line for clarity you need to end all but the last line with "\". See the make manual, Splitting Recipe Lines. Or use a shell script.
Answered By - rveerd Answer Checked By - Clifford M. (WPSolving Volunteer)