Skip to content

Instantly share code, notes, and snippets.

@rlcamp
Last active October 30, 2023 15:54
Show Gist options
  • Save rlcamp/175605ae1993eddfc854e921dc2de855 to your computer and use it in GitHub Desktop.
Save rlcamp/175605ae1993eddfc854e921dc2de855 to your computer and use it in GitHub Desktop.
calls flock(2) for various use cases, behaves like unix flock, python and perl implementations
#!/usr/bin/perl -w
use strict;
use Fcntl qw(:DEFAULT :flock);
if (!@ARGV) { die "Usage: $0 fd | { lockfile prog args }\n"; }
# get a filehandle to either the supplied filename or fd, depending on whether it is an integer
open(my $fh, $ARGV[0] =~ /^\d+$/ ? ">&=" : ">", $ARGV[0]) or die "cannot open: $!\n";
# flock the filehandle
flock($fh, LOCK_EX) or die "cannot flock: $!\n";
# if there are additional command line arguments, treat them as a command to run with the lock held
shift @ARGV;
if (@ARGV) {
# discard cloexec
fcntl($fh, F_SETFD, fcntl($fh, F_GETFD, 0) & ~FD_CLOEXEC) or die "cannot fcntl: $!\n";
exec @ARGV;
}
#!/usr/bin/env python3
from os import execvp, open, strerror, O_RDWR, O_CREAT
from stat import S_IRUSR, S_IWUSR
from fcntl import fcntl, flock, LOCK_EX, F_SETFD, F_GETFD, FD_CLOEXEC
from sys import argv
if len(argv) < 2: raise RuntimeError('usage: %s fd | { lockfile prog args}' % argv[0])
fd = int(argv[1]) if argv[1].isnumeric() else open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)
if -1 == fd: raise RuntimeError('cannot open: %s' % strerror(ctypes.get_errno))
if -1 == flock(fd, LOCK_EX): raise RuntimeError('cannot flock: %s' % strerror(ctypes.get_errno))
# if more arguments were given, treat them as a command to execute
if len(argv) > 2:
if -1 == fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC):
raise RuntimeError('cannot discard cloexec: %s' % strerror(ctypes.get_errno))
if -1 == execvp(argv[2], argv[2::]): RuntimeError('cannot exec: %s' % strerror(ctypes.get_errno))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment