/* --pidfile: Name of pidfile (null if none). */
static char *pidfile;
+/* Device and inode of pidfile, so we can avoid reopening it. */
+static dev_t pidfile_dev;
+static ino_t pidfile_ino;
+
/* --overwrite-pidfile: Create pidfile even if one already exists and is
locked? */
static bool overwrite_pidfile;
close(fd);
} else {
/* Keep 'fd' open to retain the lock. */
+ struct stat s;
+
+ if (!fstat(fd, &s)) {
+ pidfile_dev = s.st_dev;
+ pidfile_ino = s.st_ino;
+ } else {
+ VLOG_ERR("%s: fstat failed: %s",
+ pidfile, strerror(errno));
+ }
}
free(text);
} else {
{
char line[128];
struct flock lck;
+ struct stat s;
FILE *file;
int error;
+ if ((pidfile_ino || pidfile_dev)
+ && !stat(pidfile, &s)
+ && s.st_ino == pidfile_ino && s.st_dev == pidfile_dev) {
+ /* It's our own pidfile. We can't afford to open it, because closing
+ * *any* fd for a file that a process has locked also releases all the
+ * locks on that file.
+ *
+ * Fortunately, we know the associated pid anyhow: */
+ return getpid();
+ }
+
file = fopen(pidfile, "r");
if (!file) {
error = errno;
# --pidfile: Name of pidfile (null if none).
_pidfile = None
+# Our pidfile's inode and device, if we have created one.
+_pidfile_dev = None
+_pidfile_ino = None
+
# --overwrite-pidfile: Create pidfile even if one already exists and is locked?
_overwrite_pidfile = False
logging.error("%s: create failed: %s"
% (tmpfile, os.strerror(e.errno)))
return
-
+
try:
fcntl.lockf(file, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError, e:
file.close()
return
+ s = os.fstat(file.fileno())
+ _pidfile_dev = s.st_dev
+ _pidfile_ino = s.st_ino
+
def daemonize():
"""If configured with set_pidfile() or set_detach(), creates the pid file
and detaches from the foreground session."""
def read_pidfile(pidfile):
"""Opens and reads a PID from 'pidfile'. Returns the nonnegative PID if
successful, otherwise a negative errno value."""
+ if _pidfile_dev is not None:
+ try:
+ s = os.stat(pidfile)
+ if s.st_ino == _pidfile_ino and s.st_dev == _pidfile_dev:
+ # It's our own pidfile. We can't afford to open it,
+ # because closing *any* fd for a file that a process
+ # has locked also releases all the locks on that file.
+ #
+ # Fortunately, we know the associated pid anyhow.
+ return os.getpid()
+ except OSError:
+ pass
+
try:
file = open(pidfile, "r")
except IOError, e: