summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Písař <ppisar@redhat.com>2011-02-03 17:57:09 +0100
committerJan Kara <jack@suse.cz>2012-02-29 23:12:11 +0100
commit325a0e796f82aa3d1f0b47fbfc5446a6f018412a (patch)
treeed1300fd23d22830eea1cfd51b1ca7ac91bfcfcb
parent400e4b30db70482b63522ecd74a825b6373a4e19 (diff)
downloadlinuxquota-325a0e796f82aa3d1f0b47fbfc5446a6f018412a.tar.gz
Store PID of quota_nld
If quota_nld is run as daemon, daemon's PID will be stored into /var/run/${PROGNAME}.pid file and it will be deleted on receiving SIGTERM just before program termination. PID file is used by init scripts to find and kill forked daemon. Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--quota_nld.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/quota_nld.c b/quota_nld.c
index 5a53b7e..1decd96 100644
--- a/quota_nld.c
+++ b/quota_nld.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <fcntl.h>
#include <limits.h>
+#include <signal.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
@@ -374,6 +375,84 @@ static void run(struct nl_handle *nhandle)
}
}
+/* Build file name (absolute path) to PID file of this daemon.
+ * The returned name is allocated on heap. */
+static char *build_pid_file_name(void)
+{
+ char *pid_name = NULL;
+ if (!progname) {
+ errstr(_("Undefined program name.\n"));
+ return NULL;
+ }
+ pid_name = malloc(9 + strlen(progname) + 4 + 1);
+ if (!pid_name) {
+ errstr(_("Not enough memory to build PID file name.\n"));
+ return NULL;
+ }
+ sprintf(pid_name, "/var/run/%s.pid", progname);
+ return pid_name;
+}
+
+/* Store daemon's PID to file */
+static int store_pid(void)
+{
+ FILE *pid_file;
+ char *pid_name;
+
+ pid_name = build_pid_file_name();
+ if (!pid_name)
+ return -1;
+
+ pid_file = fopen(pid_name, "w");
+ if (!pid_file) {
+ errstr(_("Could not open PID file '%s': %s\n"),
+ pid_name, strerror(errno));
+ free(pid_name);
+ return -1;
+ }
+ if (fprintf(pid_file, "%jd\n", (intmax_t)getpid()) < 0) {
+ errstr(_("Could not write daemon's PID into '%s'.\n"),
+ pid_name);
+ fclose(pid_file);
+ free(pid_name);
+ return -1;
+ }
+ if (fclose(pid_file)) {
+ errstr(_("Could not close PID file '%s'.\n"), pid_name);
+ free(pid_name);
+ return -1;
+ }
+
+ free(pid_name);
+ return 0;
+}
+
+/* Handler for SIGTERM to remove PID file */
+static void remove_pid(int signal)
+{
+ char *pid_name;
+
+ pid_name = build_pid_file_name();
+ if (pid_name) {
+ unlink(pid_name);
+ free(pid_name);
+ }
+ exit(EXIT_SUCCESS);
+}
+
+/* Store daemon's PID into file and register its removal on SIGTERM */
+static void use_pid_file(void)
+{
+ struct sigaction term_action;
+
+ term_action.sa_handler = remove_pid;
+ term_action.sa_flags = 0;
+ if (sigaction(SIGTERM, &term_action, NULL))
+ errstr(_("Could not register PID file removal on SIGTERM.\n"));
+ if (store_pid())
+ errstr(_("Could not store my PID %jd.\n"), (intmax_t )getpid());
+}
+
int main(int argc, char **argv)
{
struct nl_handle *nhandle;
@@ -388,6 +467,7 @@ int main(int argc, char **argv)
if (!(flags & FL_NODAEMON)) {
use_syslog();
daemon(0, 0);
+ use_pid_file();
}
run(nhandle);
return 0;