} /* }}} void install_signal_handlers */
-static int open_pidfile(void) /* {{{ */
+static int open_pidfile(char *action, int oflag) /* {{{ */
{
int fd;
char *file;
? config_pid_file
: LOCALSTATEDIR "/run/rrdcached.pid";
- fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IRGRP|S_IROTH);
+ fd = open(file, oflag, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH);
if (fd < 0)
- fprintf(stderr, "FATAL: cannot create '%s' (%s)\n",
- file, rrd_strerror(errno));
+ fprintf(stderr, "rrdcached: can't %s pid file '%s' (%s)\n",
+ action, file, rrd_strerror(errno));
return(fd);
} /* }}} static int open_pidfile */
+/* check existing pid file to see whether a daemon is running */
+static int check_pidfile(void)
+{
+ int pid_fd;
+ pid_t pid;
+ char pid_str[16];
+
+ pid_fd = open_pidfile("open", O_RDWR);
+ if (pid_fd < 0)
+ return pid_fd;
+
+ if (read(pid_fd, pid_str, sizeof(pid_str)) <= 0)
+ return -1;
+
+ pid = atoi(pid_str);
+ if (pid <= 0)
+ return -1;
+
+ /* another running process that we can signal COULD be
+ * a competing rrdcached */
+ if (pid != getpid() && kill(pid, 0) == 0)
+ {
+ fprintf(stderr,
+ "FATAL: Another rrdcached daemon is running?? (pid %d)\n", pid);
+ close(pid_fd);
+ return -1;
+ }
+
+ lseek(pid_fd, 0, SEEK_SET);
+ ftruncate(pid_fd, 0);
+
+ fprintf(stderr,
+ "rrdcached: removed stale PID file (no rrdcached on pid %d)\n"
+ "rrdcached: starting normally.\n", pid);
+
+ return pid_fd;
+} /* }}} static int check_pidfile */
+
static int write_pidfile (int fd) /* {{{ */
{
pid_t pid;
if (values_num < 1)
{
+ /* journal replay mode */
+ if (sock == NULL) return RESP_ERR;
+
/* if we had only one update attempt, then return the full
error message... try to get the most information out
of the limited error space allowed by the protocol
sizeof (listen_fds[0]) * (listen_fds_num + 1));
if (temp == NULL)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_unix: realloc failed.");
+ fprintf (stderr, "rrdcached: open_listen_socket_unix: realloc failed.\n");
return (-1);
}
listen_fds = temp;
fd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0);
if (fd < 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_unix: socket(2) failed.");
+ fprintf (stderr, "rrdcached: unix socket(2) failed: %s\n",
+ rrd_strerror(errno));
return (-1);
}
sa.sun_family = AF_UNIX;
strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
+ /* if we've gotten this far, we own the pid file. any daemon started
+ * with the same args must not be alive. therefore, ensure that we can
+ * create the socket...
+ */
+ unlink(path);
+
status = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
if (status != 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_unix: bind(2) failed.");
+ fprintf (stderr, "rrdcached: bind(%s) failed: %s.\n",
+ path, rrd_strerror(errno));
close (fd);
- unlink (path);
return (-1);
}
status = listen (fd, /* backlog = */ 10);
if (status != 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_unix: listen(2) failed.");
+ fprintf (stderr, "rrdcached: listen(%s) failed: %s.\n",
+ path, rrd_strerror(errno));
close (fd);
unlink (path);
return (-1);
port = strchr (addr, ']');
if (port == NULL)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: Malformed address: %s",
- sock->addr);
+ fprintf (stderr, "rrdcached: Malformed address: %s\n", sock->addr);
return (-1);
}
*port = 0;
port = NULL;
else
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: Garbage after address: %s",
- port);
+ fprintf (stderr, "rrdcached: Garbage after address: %s\n", port);
return (-1);
}
} /* if (*addr = ']') */
&ai_hints, &ai_res);
if (status != 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: getaddrinfo(%s) failed: "
- "%s", addr, gai_strerror (status));
+ fprintf (stderr, "rrdcached: getaddrinfo(%s) failed: %s\n",
+ addr, gai_strerror (status));
return (-1);
}
sizeof (listen_fds[0]) * (listen_fds_num + 1));
if (temp == NULL)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: realloc failed.");
+ fprintf (stderr,
+ "rrdcached: open_listen_socket_network: realloc failed.\n");
continue;
}
listen_fds = temp;
fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
if (fd < 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: socket(2) failed.");
+ fprintf (stderr, "rrdcached: network socket(2) failed: %s.\n",
+ rrd_strerror(errno));
continue;
}
status = bind (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
if (status != 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: bind(2) failed.");
+ fprintf (stderr, "rrdcached: bind(%s) failed: %s.\n",
+ sock->addr, rrd_strerror(errno));
close (fd);
continue;
}
status = listen (fd, /* backlog = */ 10);
if (status != 0)
{
- RRDD_LOG (LOG_ERR, "open_listen_socket_network: listen(2) failed.");
+ fprintf (stderr, "rrdcached: listen(%s) failed: %s\n.",
+ sock->addr, rrd_strerror(errno));
close (fd);
return (-1);
}
int status;
int i;
- for (i = 0; i < config_listen_address_list_len; i++)
- open_listen_socket (config_listen_address_list[i]);
-
- if (config_listen_address_list_len < 1)
- {
- listen_socket_t sock;
- memset(&sock, 0, sizeof(sock));
- strncpy(sock.addr, RRDCACHED_DEFAULT_ADDRESS, sizeof(sock.addr));
- open_listen_socket (&sock);
- }
-
if (listen_fds_num < 1)
{
- RRDD_LOG (LOG_ERR, "listen_thread_main: No listen sockets "
- "could be opened. Sorry.");
+ RRDD_LOG(LOG_ERR, "listen_thread_main: no listen_fds !");
return (NULL);
}
static int daemonize (void) /* {{{ */
{
- int status;
- int fd;
+ int pid_fd;
char *base_dir;
daemon_uid = geteuid();
- fd = open_pidfile();
- if (fd < 0) return fd;
+ pid_fd = open_pidfile("create", O_CREAT|O_EXCL|O_WRONLY);
+ if (pid_fd < 0)
+ pid_fd = check_pidfile();
+ if (pid_fd < 0)
+ return pid_fd;
+
+ /* open all the listen sockets */
+ if (config_listen_address_list_len > 0)
+ {
+ for (int i = 0; i < config_listen_address_list_len; i++)
+ open_listen_socket (config_listen_address_list[i]);
+ }
+ else
+ {
+ listen_socket_t sock;
+ memset(&sock, 0, sizeof(sock));
+ strncpy(sock.addr, RRDCACHED_DEFAULT_ADDRESS, sizeof(sock.addr));
+ open_listen_socket (&sock);
+ }
+
+ if (listen_fds_num < 1)
+ {
+ fprintf (stderr, "rrdcached: FATAL: cannot open any listen sockets\n");
+ goto error;
+ }
if (!stay_foreground)
{
if (child < 0)
{
fprintf (stderr, "daemonize: fork(2) failed.\n");
- return (-1);
+ goto error;
}
else if (child > 0)
- {
- return (1);
- }
+ exit(0);
/* Become session leader */
setsid ();
base_dir = (config_base_dir != NULL)
? config_base_dir
: "/tmp";
- status = chdir (base_dir);
- if (status != 0)
+
+ if (chdir (base_dir) != 0)
{
fprintf (stderr, "daemonize: chdir (%s) failed.\n", base_dir);
- return (-1);
+ goto error;
}
install_signal_handlers();
if (cache_tree == NULL)
{
RRDD_LOG (LOG_ERR, "daemonize: g_tree_new failed.");
- return (-1);
+ goto error;
}
- status = write_pidfile (fd);
- return status;
+ return write_pidfile (pid_fd);
+
+error:
+ remove_pidfile();
+ return -1;
} /* }}} int daemonize */
static int cleanup (void) /* {{{ */
}
status = daemonize ();
- if (status == 1)
- {
- struct sigaction sigchld;
-
- memset (&sigchld, 0, sizeof (sigchld));
- sigchld.sa_handler = SIG_IGN;
- sigaction (SIGCHLD, &sigchld, NULL);
-
- return (0);
- }
- else if (status != 0)
+ if (status != 0)
{
- fprintf (stderr, "daemonize failed, exiting.\n");
+ fprintf (stderr, "rrdcached: daemonize failed, exiting.\n");
return (1);
}