[PATCH] Skip writing pidfile when old and new paths are equivalent

Corey Kasten coreykasten at gmail.com
Mon Feb 29 18:57:49 UTC 2016


# HG changeset patch
# User Corey Kasten <coreykasten at gmail.com>
# Date 1456771518 28800
#      Mon Feb 29 10:45:18 2016 -0800
# Node ID a2365d15b75c9537efacbef038a67dde693a7f0f
# Parent  8e6f34342eb652046fdfcd0d0677f0d20483c0a5
Skip writing pidfile when old and new paths are equivalent

On an nginx reload, if the pidfile path has changed, the pid is written to the
new path, and the old file is deleted. This behaviour is problematic when the
old path (e.g. /run/nginx.pid) is equivalent to the new path
(e.g. /var/run/nginx.pid), due to the use of a symbolic link (/var/run -> /run).
After deleting the file at the old path, we are left without a .pid file,
since the new and old were actually the same file. The solution employed here
is to check whether the two paths resolve to the same inode via stat(2).

diff -r 8e6f34342eb6 -r a2365d15b75c src/core/ngx_cycle.c
--- a/src/core/ngx_cycle.c	Mon Feb 29 18:52:33 2016 +0300
+++ b/src/core/ngx_cycle.c	Mon Feb 29 10:45:18 2016 -0800
@@ -15,6 +15,7 @@
     ngx_shm_zone_t *shm_zone);
 static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
 static void ngx_clean_old_cycles(ngx_event_t *ev);
+static int are_same_file(u_char *file1, u_char *file2);
 
 
 volatile ngx_cycle_t  *ngx_cycle;
@@ -322,8 +323,9 @@
 
         old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx,
                                                    ngx_core_module);
-        if (ccf->pid.len != old_ccf->pid.len
+        if ((ccf->pid.len != old_ccf->pid.len
             || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0)
+            && !are_same_file(ccf->pid.data,  old_ccf->pid.data))
         {
             /* new pid file name */
 
@@ -1337,3 +1339,32 @@
         ngx_old_cycles.nelts = 0;
     }
 }
+ 
+static int
+are_same_file(u_char *file1, u_char *file2)
+{
+#if !(NGX_WIN32)
+    ngx_file_info_t  fi1, fi2;
+
+    if (ngx_file_info((const char *) file1, &fi1) == NGX_FILE_ERROR)
+    {
+        return 0;
+    }
+
+    if (ngx_file_info((const char *) file2, &fi2) == NGX_FILE_ERROR)
+    {
+        return 0;
+    }
+
+    if (fi1.st_ino != fi2.st_ino ||
+        major(fi1.st_dev) != major(fi2.st_dev) ||
+        minor(fi1.st_dev) != minor(fi2.st_dev))
+    {
+        return 0;
+    }
+
+    return 1;
+#else
+    return 0;
+#endif
+}



More information about the nginx-devel mailing list