From 8ae10eba01e3cf65a106b568698f439c4f54efbd Mon Sep 17 00:00:00 2001 From: Kenneth Steele Date: Mon, 14 May 2012 15:39:46 -0400 Subject: Create memcached pid file atomically using rename. This change avoids a race condition where another application (e.g., testapp) can read the memcached pid file after memcached opens it, but before memcached writes the pid. It now writes the pid into a temporary file and then renames that file to the correct pid file name. This way the pid file can not exist without containing the correct value. --- memcached.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/memcached.c b/memcached.c index 86dfe88..b6ed7c9 100644 --- a/memcached.c +++ b/memcached.c @@ -4603,14 +4603,27 @@ static void save_pid(const char *pid_file) { } } - if ((fp = fopen(pid_file, "w")) == NULL) { - vperror("Could not open the pid file %s for writing", pid_file); + /* Create the pid file first with a temporary name, then + * atomically move the file to the real name to avoid a race with + * another process opening the file to read the pid, but finding + * it empty. + */ + char tmp_pid_file[1024]; + snprintf(tmp_pid_file, sizeof(tmp_pid_file), "%s.tmp", pid_file); + + if ((fp = fopen(tmp_pid_file, "w")) == NULL) { + vperror("Could not open the pid file %s for writing", tmp_pid_file); return; } fprintf(fp,"%ld\n", (long)getpid()); if (fclose(fp) == -1) { - vperror("Could not close the pid file %s", pid_file); + vperror("Could not close the pid file %s", tmp_pid_file); + } + + if (rename(tmp_pid_file, pid_file) != 0) { + vperror("Could not rename the pid file from %s to %s", + tmp_pid_file, pid_file); } } -- cgit v1.2.1