diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-10-12 07:00:58 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-10-12 07:24:11 +0000 |
commit | e8217a1fe0cf341b7219a426f23e02cb44281301 (patch) | |
tree | 1d278c304ffdced66de855fad07ac2413336740e /svc.c | |
parent | a4126a4bef3708c6f3b63f8a8877a3ce2213470b (diff) | |
download | cmogstored-e8217a1fe0cf341b7219a426f23e02cb44281301.tar.gz |
readdir on the same DIR pointer is undefined if DIR was inherited by multiple children. Using the reentrant readdir_r would not have helped, since the underlying file descriptor and kernel file handle were still shared (and we need rewinddir, too). This readdir usage bug existed in cmogstored since the earliest releases, but was harmless until the cmogstored 1.3 series. This misuse of readdir lead to hitting a leftover call to free(). So this bug only manifested since commit 1fab1e7a7f03f3bc0abb1b5181117f2d4605ce3b (svc: implement top-level by_mog_devid hash) Fortunately, these bugs only affect users of the undocumented multi-process feature (not just multi-threaded).
Diffstat (limited to 'svc.c')
-rw-r--r-- | svc.c | 29 |
1 files changed, 29 insertions, 0 deletions
@@ -69,6 +69,35 @@ static void svc_once(void) atexit(svc_atexit); } +bool mog_svc_atfork_child(void *svc_ptr, void *parent) +{ + struct mog_svc *svc = svc_ptr; + pid_t ppid = *((pid_t *)parent); + const char *failfn; + + if (closedir(svc->dir) < 0) { + failfn = "closedir"; + goto err; + } + + svc->dir = opendir(svc->docroot); + if (svc->dir == NULL) { + failfn = "opendir"; + goto err; + } + + svc->docroot_fd = dirfd(svc->dir); + if (svc->docroot_fd < 0) { + failfn = "dirfd"; + goto err; + } + return true; +err: + syslog(LOG_ERR, "%s(%s) failed with: %m", failfn, svc->docroot); + kill(ppid, SIGTERM); + return false; +} + struct mog_svc * mog_svc_new(const char *docroot) { struct mog_svc *svc; |