1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/debug.h"
16 #include "common/errno.h"
17 #include "common/safe_io.h"
18 #include "global/pidfile.h"
23 #include <sys/types.h>
26 #if defined(__FreeBSD__)
27 #include <sys/param.h>
30 #include "include/compat.h"
33 // derr can be used for functions exclusively called from pidfile_write
35 // cerr must be used for functions called by pidfile_remove because
36 // logging is not functional when it is called. cerr output is lost
37 // when the caller is daemonized but it will show if not (-f)
39 #define dout_context g_ceph_context
40 #define dout_prefix *_dout
41 #define dout_subsys ceph_subsys_
45 char pf_path[PATH_MAX + 1];
57 return pf_path[0] != '\0' && pf_fd != -1;
61 memset(pf_path, 0, sizeof(pf_path));
67 int open(const md_config_t *conf);
71 static pidfh *pfh = nullptr;
74 // check that the file we opened still is the same
78 if (stat(pf_path, &st) == -1)
80 if (st.st_dev != pf_dev || st.st_ino != pf_ino)
91 if ((ret = verify()) < 0) {
99 // seek to the beginning of the file before reading
100 ret = ::lseek(pf_fd, 0, SEEK_SET);
102 std::cerr << __func__ << " lseek failed "
103 << cpp_strerror(errno) << std::endl;
107 // check that the pid file still has our pid in it
109 memset(buf, 0, sizeof(buf));
110 ssize_t res = safe_read(pf_fd, buf, sizeof(buf));
113 std::cerr << __func__ << " safe_read failed "
114 << cpp_strerror(-res) << std::endl;
120 std::cerr << __func__ << " the pid found in the file is "
121 << a << " which is different from getpid() "
122 << getpid() << std::endl;
125 ret = ::unlink(pf_path);
127 std::cerr << __func__ << " unlink " << pf_path << " failed "
128 << cpp_strerror(errno) << std::endl;
135 int pidfh::open(const md_config_t *conf)
137 int len = snprintf(pf_path, sizeof(pf_path),
138 "%s", conf->pid_file.c_str());
140 if (len >= (int)sizeof(pf_path))
141 return -ENAMETOOLONG;
144 fd = ::open(pf_path, O_CREAT|O_RDWR, 0644);
147 derr << __func__ << ": failed to open pid file '"
148 << pf_path << "': " << cpp_strerror(err) << dendl;
153 if (fstat(fd, &st) == -1) {
155 derr << __func__ << ": failed to fstat pid file '"
156 << pf_path << "': " << cpp_strerror(err) << dendl;
168 .l_whence = SEEK_SET,
172 int r = ::fcntl(pf_fd, F_SETLK, &l);
174 derr << __func__ << ": failed to lock pidfile "
175 << pf_path << " because another process locked it." << dendl;
189 int len = snprintf(buf, sizeof(buf), "%d\n", getpid());
190 if (::ftruncate(pf_fd, 0) < 0) {
192 derr << __func__ << ": failed to ftruncate the pid file '"
193 << pf_path << "': " << cpp_strerror(err) << dendl;
196 ssize_t res = safe_write(pf_fd, buf, len);
198 derr << __func__ << ": failed to write to pid file '"
199 << pf_path << "': " << cpp_strerror(-res) << dendl;
205 void pidfile_remove()
212 int pidfile_write(const md_config_t *conf)
214 if (conf->pid_file.empty()) {
215 dout(0) << __func__ << ": ignore empty --pid-file" << dendl;
219 assert(pfh == nullptr);
222 if (atexit(pidfile_remove)) {
223 derr << __func__ << ": failed to set pidfile_remove function "
224 << "to run at exit." << dendl;
228 int r = pfh->open(conf);