Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support daemon and pidfile. #136

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ corvus_test
.*.sw[pon]

.cache
tags
src/tags
*.patch
8 changes: 8 additions & 0 deletions corvus.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ bind 12345
node localhost:8000,localhost:8001,localhost:8002
thread 4

# pidfile settings
pidfile /tmp/corvus.pid

# daemon setting
# 0: not daemon
# 1: run as a daemon
daemon 0

# debug, info, warn, error
loglevel debug
syslog 0
Expand Down
19 changes: 19 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const char * CONFIG_OPTIONS[] = {
"slowlog-log-slower-than",
"slowlog-max-len",
"slowlog-statsd-enabled",
"pidfile",
"daemon",
};

void config_init()
Expand All @@ -60,6 +62,8 @@ void config_init()
config.slowlog_max_len = 1024;
config.slowlog_log_slower_than = -1;
config.slowlog_statsd_enabled = 0;
config.pidfile = 0;
config.daemon = 0;

memset(config.statsd_addr, 0, sizeof(config.statsd_addr));
config.metric_interval = 10;
Expand Down Expand Up @@ -282,6 +286,13 @@ int config_add(char *name, char *value)
config.slowlog_max_len = val;
} else if (strcmp(name, "slowlog-statsd-enabled") == 0) {
config_boolean(&config.slowlog_statsd_enabled, value);
} else if (strcmp(name, "pidfile") == 0) {
if (strlen(value) > 0) {
config.pidfile = cv_calloc(strlen(value) + 1, sizeof(char));
memcpy(config.pidfile, value, strlen(value));
}
} else if (strcmp(name, "daemon") == 0) {
config_boolean(&config.daemon, value);
}
return CORVUS_OK;
}
Expand Down Expand Up @@ -335,6 +346,14 @@ int config_get(const char *name, char *value, size_t max_len)
snprintf(value, max_len, "%d", config.slowlog_max_len);
} else if (strcmp(name, "slowlog-statsd-enabled") == 0) {
strncpy(value, BOOL_STR(config.slowlog_statsd_enabled), max_len);
} else if (strcmp(name, "pidfile") == 0) {
if (config.pidfile) {
strncpy(value, config.pidfile, max_len);
} else {
strncpy(value, "", max_len);
}
} else if (strcmp(name, "daemon") == 0) {
strncpy(value, BOOL_STR(config.daemon), max_len);
} else {
return CORVUS_ERR;
}
Expand Down
5 changes: 4 additions & 1 deletion src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#define CLUSTER_NAME_SIZE 127
#define CONFIG_FILE_PATH_SIZE 256
#define PIDFILE_MAX_LEN 24

struct node_conf {
struct address *addr;
Expand Down Expand Up @@ -32,6 +33,8 @@ struct corvus_config {
int slowlog_log_slower_than;
int slowlog_max_len;
bool slowlog_statsd_enabled;
char *pidfile;
bool daemon;
} config;

void config_init();
Expand All @@ -47,4 +50,4 @@ void config_node_dec_ref(struct node_conf *node);
int config_add(char *name, char *value);
bool config_option_changable(const char *option);

#endif /* end of include guard: CONFIG_H */
#endif /* end of include guard: CONFIG_H */
57 changes: 56 additions & 1 deletion src/corvus.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <execinfo.h>
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "corvus.h"
#include "mbuf.h"
#include "slot.h"
Expand All @@ -17,6 +19,7 @@
#include "dict.h"
#include "timer.h"
#include "alloc.h"
#include "daemon.h"

static pthread_spinlock_t signal_lock;
static struct context *contexts;
Expand Down Expand Up @@ -324,6 +327,8 @@ static const struct option opts[] = {
{"slowlog-time", required_argument, NULL, 'g'},
{"slowlog-max", required_argument, NULL, 'G'},
{"slowlog-statsd", required_argument, NULL, 'E'},
{"pidfile", optional_argument, NULL, 'p'},
{"daemon", no_argument, NULL, 'd'},
{ 0, 0, 0, 0 },
};

Expand All @@ -344,6 +349,8 @@ static const char *opts_desc[] = {
"slowlog time in microseconds",
"slowlog max len",
"slowlog whether writing to statsd",
"set pid file",
"run as a daemon",
};

static void usage(const char *cmd)
Expand All @@ -363,7 +370,7 @@ static int parameter_init(int argc, const char *argv[]) {
int ch;
opterr = optind = 0;
do {
ch = getopt_long(argc, (char * const *)argv, ":n:t:c:b:l:s:B:C:S:A:m:L:P:g:G:E:", opts, NULL);
ch = getopt_long(argc, (char * const *)argv, ":n:t:c:b:l:s:B:C:S:A:m:L:P:g:G:E:p:d:", opts, NULL);
if (ch < 0) {
break;
}
Expand Down Expand Up @@ -416,6 +423,12 @@ static int parameter_init(int argc, const char *argv[]) {
case 'E':
config_add("slowlog-statsd-enabled", optarg);
break;
case 'p':
config_add("pidfile", optarg);
break;
case 'd':
config_add("daemon", optarg);
break;
default:
fprintf(stderr, "unknow option: %c\n", ch);
return CORVUS_ERR;
Expand All @@ -424,6 +437,38 @@ static int parameter_init(int argc, const char *argv[]) {
return CORVUS_OK;
}


int create_pidfile() {
char pid[PIDFILE_MAX_LEN];
int fd, pid_len;
fd = open(config.pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
LOG(ERROR, "open pidfile failed: %s", strerror(errno));
return CORVUS_ERR;
}

pid_len = snprintf(pid, PIDFILE_MAX_LEN, "%d", getpid());

ssize_t n;
n = write(fd, pid, pid_len);
if (n < 0) {
LOG(ERROR, "write to pidfile failed: %s", strerror(errno));
return CORVUS_ERR;
}

close(fd);

return CORVUS_OK;
}
void remove_pidfile() {
int status;
status= unlink(config.pidfile);
if (status < 0) {
LOG(ERROR, "unlink pid file '%s' failed: %s",
config.pidfile, strerror(errno));
}
}

int main(int argc, const char *argv[])
{
int i, err;
Expand Down Expand Up @@ -464,6 +509,12 @@ int main(int argc, const char *argv[])
openlog(NULL, LOG_NDELAY | LOG_NOWAIT, LOG_USER);
}

if (config.daemon)
daemonize();

if (config.pidfile)
create_pidfile();

// allocate memory for `contexts`
build_contexts();

Expand Down Expand Up @@ -529,6 +580,10 @@ int main(int argc, const char *argv[])
destroy_contexts();
cmd_map_destroy();
cv_free(config.requirepass);
if (config.pidfile) {
remove_pidfile();
cv_free(config.pidfile);
}
config_free();
if (config.syslog) closelog();
return EXIT_SUCCESS;
Expand Down
83 changes: 83 additions & 0 deletions src/daemon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include "corvus.h"
#include "logging.h"
#include "daemon.h"

int daemonize() {
int status;
pid_t pid, sid;
int fd;

pid = fork();
switch (pid) {
case -1:
LOG(ERROR, "fork() failed: %s", strerror(errno));
return CORVUS_ERR;
case 0:
break;
default:
/* parent */
exit(0);
}

/* The first child is the session leader */
sid = setsid();
if (sid < 0) {
LOG(ERROR, "setsid() failed: %s", strerror(errno));
return CORVUS_ERR;
}

pid = fork();
switch (pid) {
case -1:
LOG(ERROR, "fork() failed: %s", strerror(errno));
return CORVUS_ERR;
case 0:
break;
default:
/* the first child terminates */
exit(0);
}

/* the second child continues */
umask(0);

/* redirect stdin,stdout,stderr to /dev/null */
fd = open("/dev/null", O_RDWR);
if (fd < 0) {
LOG(ERROR, "open(\"/dev/null\") failed: %s", strerror(errno));
return CORVUS_ERR;
}

status = dup2(fd, STDIN_FILENO);
if (status < 0) {
LOG(ERROR, "dup2(%d, STDIN) failed: %s", fd, strerror(errno));
close(fd);
return CORVUS_ERR;
}
status = dup2(fd, STDOUT_FILENO);
if (status < 0) {
LOG(ERROR, "dup2(%d, STDOUT) failed: %s", fd, strerror(errno));
close(fd);
return CORVUS_ERR;
}
status = dup2(fd, STDERR_FILENO);
if (status < 0) {
LOG(ERROR, "dup2(%d, STDERR) failed: %s", fd, strerror(errno));
close(fd);
return CORVUS_ERR;
}
if (fd > STDERR_FILENO) {
status = close(fd);
if (status < 0) {
LOG(ERROR, "close(%d) failed: %s", fd, strerror(errno));
close(fd);
return CORVUS_ERR;
}
}
return CORVUS_OK;
}
6 changes: 6 additions & 0 deletions src/daemon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef DAEMON_H
#define DAEMON_H

int daemonize();

#endif /* end of include guard: DAEMON_H */