mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-10-20 12:54:15 -04:00
Use a lock to not fail on a left-over pid file.
This commit is contained in:
1 parent
778f0dff9b
commit
b177311aee
3 files changed
+55
-17
No files matched your search
+48
-14
@@ -66,6 +66,7 @@ extern gid_t our_gid;
|
||||
char *auth_user;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int pid_file_fd = -1;
|
||||
struct chmod_mode_struct *daemon_chmod_modes;
|
||||
|
||||
/* module_dirlen is the length of the module_dir string when in daemon
|
||||
@@ -1149,26 +1150,59 @@ int start_daemon(int f_in, int f_out)
|
||||
static void create_pid_file(void)
|
||||
{
|
||||
char *pid_file = lp_pid_file();
|
||||
char pidbuf[16];
|
||||
pid_t pid = getpid();
|
||||
int fd, len;
|
||||
char pidbuf[32];
|
||||
STRUCT_STAT st1, st2;
|
||||
char *fail = NULL;
|
||||
|
||||
if (!pid_file || !*pid_file)
|
||||
return;
|
||||
|
||||
cleanup_set_pid(pid);
|
||||
if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666)) == -1) {
|
||||
failure:
|
||||
cleanup_set_pid(0);
|
||||
fprintf(stderr, "failed to create pid file %s: %s\n", pid_file, strerror(errno));
|
||||
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
|
||||
/* These tests make sure that a temp-style lock dir is handled safely. */
|
||||
st1.st_mode = 0;
|
||||
if (do_lstat(pid_file, &st1) == 0 && !S_ISREG(st1.st_mode) && unlink(pid_file) < 0)
|
||||
fail = "unlink";
|
||||
else if ((pid_file_fd = do_open(pid_file, O_RDWR|O_CREAT, 0664)) < 0)
|
||||
fail = S_ISREG(st1.st_mode) ? "open" : "create";
|
||||
else if (!lock_range(pid_file_fd, 0, 4))
|
||||
fail = "lock";
|
||||
else if (do_fstat(pid_file_fd, &st1) < 0)
|
||||
fail = "fstat opened";
|
||||
else if (st1.st_size >= (int)sizeof pidbuf)
|
||||
fail = "find small";
|
||||
else if (do_lstat(pid_file, &st2) < 0)
|
||||
fail = "lstat";
|
||||
else if (!S_ISREG(st1.st_mode))
|
||||
fail = "avoid file overwrite race for";
|
||||
else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
|
||||
fail = "verify stat info for";
|
||||
#ifdef HAVE_FTRUNCATE
|
||||
else if (do_ftruncate(pid_file_fd, 0) < 0)
|
||||
fail = "truncate";
|
||||
#endif
|
||||
else {
|
||||
pid_t pid = getpid();
|
||||
int len = snprintf(pidbuf, sizeof pidbuf, "%d\n", (int)pid);
|
||||
#ifndef HAVE_FTRUNCATE
|
||||
/* What can we do with a too-long file and no truncate? I guess we'll add extra newlines. */
|
||||
while (len < st1.st_size) /* We already verfified that size+1 chars fits in the buffer. */
|
||||
pidbuf[len++] = '\n';
|
||||
/* We don't need the buffer to end in a '\0' (and we may not have room to add it). */
|
||||
#endif
|
||||
if (write(pid_file_fd, pidbuf, len) != len)
|
||||
fail = "write";
|
||||
cleanup_set_pid(pid); /* Mark the file for removal on exit, even if the write failed. */
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
char msg[1024];
|
||||
snprintf(msg, sizeof msg, "failed to %s pid file %s: %s\n",
|
||||
fail, pid_file, strerror(errno));
|
||||
fputs(msg, stderr);
|
||||
rprintf(FLOG, "%s", msg);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
snprintf(pidbuf, sizeof pidbuf, "%d\n", (int)pid);
|
||||
len = strlen(pidbuf);
|
||||
if (write(fd, pidbuf, len) != len)
|
||||
goto failure;
|
||||
close(fd);
|
||||
|
||||
/* The file is left open so that the lock remains valid. It is closed in our forked child procs. */
|
||||
}
|
||||
|
||||
/* Become a daemon, discarding the controlling terminal. */
|
||||
|
||||
+4
-3
@@ -103,9 +103,10 @@ This can be overridden by the bf(--dparam=motdfile=FILE)
|
||||
command-line option when starting the daemon.
|
||||
|
||||
dit(bf(pid file)) This parameter tells the rsync daemon to write
|
||||
its process ID to that file. If the file already exists, the rsync
|
||||
daemon will abort rather than overwrite the file.
|
||||
This can be overridden by the bf(--dparam=pidfile=FILE)
|
||||
its process ID to that file. The rsync keeps the file locked so that
|
||||
it can know when it is safe to overwrite an existing file.
|
||||
|
||||
The filename can be overridden by the bf(--dparam=pidfile=FILE)
|
||||
command-line option when starting the daemon.
|
||||
|
||||
dit(bf(port)) You can override the default port the daemon will listen on
|
||||
|
||||
@@ -38,6 +38,7 @@ extern char *bind_address;
|
||||
extern char *sockopts;
|
||||
extern int default_af_hint;
|
||||
extern int connect_timeout;
|
||||
extern int pid_file_fd;
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
static struct sigaction sigact;
|
||||
@@ -609,6 +610,8 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
int ret;
|
||||
if (pid_file_fd >= 0)
|
||||
close(pid_file_fd);
|
||||
for (i = 0; sp[i] >= 0; i++)
|
||||
close(sp[i]);
|
||||
/* Re-open log file in child before possibly giving
|
||||
|
||||
Reference in new issue
Block a user