{
if (g_code_env != CODE_ENVIRONMENT_DAEMON)
return -1;
+
const md_config_t *conf = cct->_conf;
if (!conf->daemonize) {
+
+ if (pidfile_open(g_conf) < 0) {
+ exit(1);
+ }
+
if (atexit(pidfile_remove_void)) {
derr << "global_init_daemonize: failed to set pidfile_remove function "
<< "to run at exit." << dendl;
}
-
- pidfile_write(g_conf);
+ pidfile_write();
return -1;
}
<< cpp_strerror(ret) << dendl;
exit(1);
}
-
+
global_init_postfork_start(cct);
global_init_postfork_finish(cct, flags);
}
// restart log thread
g_ceph_context->_log->start();
+ if (pidfile_open(g_conf) < 0) {
+ exit(1);
+ }
+
if (atexit(pidfile_remove_void)) {
derr << "global_init_daemonize: failed to set pidfile_remove function "
<< "to run at exit." << dendl;
exit(1);
}
- pidfile_write(g_conf);
+ pidfile_write();
}
void global_init_postfork_finish(CephContext *cct, int flags)
#define dout_prefix *_dout
-static char pid_file[PATH_MAX] = "";
+struct pidfh {
+ int pf_fd;
+ char pf_path[PATH_MAX + 1];
+ dev_t pf_dev;
+ ino_t pf_ino;
+
+ pidfh() : pf_fd(-1), pf_dev(0), pf_ino(0) {
+ memset(pf_path, 0, sizeof(pf_path));
+ }
+
+ void close() {
+ pf_fd = -1;
+ pf_path[0] = '\0';
+ pf_dev = 0;
+ pf_ino = 0;
+ }
+};
+static pidfh pfh;
-int pidfile_write(const md_config_t *conf)
-{
- int ret, fd;
+static int pidfile_verify() {
+ struct stat st;
- if (conf->pid_file.empty()) {
- return pidfile_remove();
+ if (pfh.pf_fd == -1) {
+ return -EINVAL;
+ }
+ /*
+ * Check remembered descriptor
+ */
+ if (fstat(pfh.pf_fd, &st) == -1) {
+ return -errno;
}
- snprintf(pid_file, PATH_MAX, "%s", conf->pid_file.c_str());
- fd = TEMP_FAILURE_RETRY(::open(pid_file,
- O_CREAT|O_TRUNC|O_WRONLY, 0644));
- if (fd < 0) {
- int err = errno;
- derr << "write_pid_file: failed to open pid file '"
- << pid_file << "': " << cpp_strerror(err) << dendl;
- return err;
+ if (st.st_dev != pfh.pf_dev || st.st_ino != pfh.pf_ino) {
+ return -ESTALE;
+ }
+ return 0;
+}
+
+int pidfile_write()
+{
+ if (!pfh.pf_path[0]) {
+ return 0;
}
- char buf[20];
+ int ret;
+ if ((ret = pidfile_verify()) < 0) {
+ return ret;
+ }
+
+ char buf[32];
int len = snprintf(buf, sizeof(buf), "%d\n", getpid());
- ret = safe_write(fd, buf, len);
+ ret = safe_write(pfh.pf_fd, buf, len);
if (ret < 0) {
derr << "write_pid_file: failed to write to pid file '"
- << pid_file << "': " << cpp_strerror(ret) << dendl;
- VOID_TEMP_FAILURE_RETRY(::close(fd));
+ << pfh.pf_path << "': " << cpp_strerror(ret) << dendl;
+ pfh.close();
return ret;
}
- if (TEMP_FAILURE_RETRY(::close(fd))) {
- ret = errno;
- derr << "SimpleMessenger::write_pid_file: failed to close to pid file '"
- << pid_file << "': " << cpp_strerror(ret) << dendl;
- return -ret;
- }
return 0;
}
-int pidfile_remove(void)
+int pidfile_remove()
{
- if (!pid_file[0])
+ if (!pfh.pf_path[0]) {
return 0;
+ }
+
+ int ret;
+ if ((ret = pidfile_verify()) < 0) {
+ if (pfh.pf_fd != -1) {
+ ::close(pfh.pf_fd);
+ }
+ return ret;
+ }
// only remove it if it has OUR pid in it!
- int fd = TEMP_FAILURE_RETRY(::open(pid_file, O_RDONLY));
- if (fd < 0)
- return -errno;
char buf[32];
memset(buf, 0, sizeof(buf));
- ssize_t res = safe_read(fd, buf, sizeof(buf));
- VOID_TEMP_FAILURE_RETRY(::close(fd));
- if (res < 0)
+ ssize_t res = safe_read(pfh.pf_fd, buf, sizeof(buf));
+ if (pfh.pf_fd != -1) {
+ ::close(pfh.pf_fd);
+ }
+
+ if (res < 0) {
return res;
+ }
+
int a = atoi(buf);
- if (a != getpid())
+ if (a != getpid()) {
return -EDOM;
-
- res = ::unlink(pid_file);
- if (res)
+ }
+ res = ::unlink(pfh.pf_path);
+ if (res) {
return res;
+ }
+ pfh.close();
+ return 0;
+}
+
+int pidfile_open(const md_config_t *conf)
+{
+ if (conf->pid_file.empty()) {
+ return 0;
+ }
+ int len = snprintf(pfh.pf_path, sizeof(pfh.pf_path),
+ "%s", conf->pid_file.c_str());
+
+ if (len >= (int)sizeof(pfh.pf_path)) {
+ return -ENAMETOOLONG;
+ }
- pid_file[0] = '\0';
+ int fd;
+ fd = ::open(pfh.pf_path, O_CREAT|O_WRONLY, 0644);
+ if (fd < 0) {
+ int err = errno;
+ derr << "write_pid_file: failed to open pid file '"
+ << pfh.pf_path << "': " << cpp_strerror(err) << dendl;
+ pfh.close();
+ return -errno;
+ }
+ struct stat st;
+ if (fstat(fd, &st) == -1) {
+ close(fd);
+ pfh.close();
+ return -errno;
+ }
+ pfh.pf_fd = fd;
+ pfh.pf_dev = st.st_dev;
+ pfh.pf_ino = st.st_ino;
+
+ struct flock l = { F_WRLCK, SEEK_SET, 0, 0, 0 };
+ int r = ::fcntl(pfh.pf_fd, F_SETLK, &l);
+ if (r < 0) {
+ derr << "failed to lock pidfile - " << pfh.pf_path << ". is there another process in use?" << dendl;
+ close(pfh.pf_fd);
+ pfh.close();
+ return -errno;
+ }
return 0;
}