diff --git a/src/Makefile b/src/Makefile index 0aa409de53ba916085e78107bcc51f5b918b5171..9202fb4bd97ac1fca160e8efa823efe4489b5709 100644 --- a/src/Makefile +++ b/src/Makefile @@ -99,7 +99,7 @@ endif REDIS_SERVER_NAME= redis-server REDIS_SENTINEL_NAME= redis-sentinel -REDIS_SERVER_OBJ= adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o +REDIS_SERVER_OBJ= adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o migrate.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o REDIS_CLI_NAME= redis-cli REDIS_CLI_OBJ= anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o REDIS_BENCHMARK_NAME= redis-benchmark diff --git a/src/Makefile.dep b/src/Makefile.dep index 35025070c7e84d94002b4e9854f6c5c3b00663f8..784b272af38ab069970ecd0a0faac214bd20866b 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -82,6 +82,7 @@ sentinel.o: sentinel.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \ ziplist.h intset.h version.h util.h rdb.h rio.h \ ../deps/hiredis/hiredis.h ../deps/hiredis/async.h \ ../deps/hiredis/hiredis.h +setproctitle.o: setproctitle.c sha1.o: sha1.c sha1.h config.h slowlog.o: slowlog.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \ ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \ diff --git a/src/aof.c b/src/aof.c index 2265222cc6dbf3e592dc810bcdfa2a700745cb82..c45265010e4267b188035d035f3ae1a2e7826fe7 100644 --- a/src/aof.c +++ b/src/aof.c @@ -961,6 +961,7 @@ int rewriteAppendOnlyFileBackground(void) { /* Child */ if (server.ipfd > 0) close(server.ipfd); if (server.sofd > 0) close(server.sofd); + redisSetProcTitle("redis-aof-rewrite"); snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid()); if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK) { size_t private_dirty = zmalloc_get_private_dirty(); diff --git a/src/config.h b/src/config.h index 68e99b427d28a3deddf5c01beb4ef9e6180c51e2..961503c6325317f497aa025fca7aaae83eb844ea 100644 --- a/src/config.h +++ b/src/config.h @@ -105,6 +105,18 @@ #define rdb_fsync_range(fd,off,size) fsync(fd) #endif +/* Check if we can use setproctitle(). + * BSD systems have support for it, we provide an implementation for + * Linux and osx. */ +#if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__) +#define USE_SETPROCTITLE +#endif + +#if (defined __linux || defined __APPLE__) +#define USE_SETPROCTITLE +void setproctitle(const char *fmt, ...); +#endif + /* Byte ordering detection */ #include /* This will likely define BYTE_ORDER */ diff --git a/src/rdb.c b/src/rdb.c index a5e4c47af429fe41989c017c9b098921fa510eb7..e327cd8cb121be4eae18f729041d8fc9fe4c1e14 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -730,6 +730,7 @@ int rdbSaveBackground(char *filename) { /* Child */ if (server.ipfd > 0) close(server.ipfd); if (server.sofd > 0) close(server.sofd); + redisSetProcTitle("redis-rdb-bgsave"); retval = rdbSave(filename); if (retval == REDIS_OK) { size_t private_dirty = zmalloc_get_private_dirty(); diff --git a/src/redis.c b/src/redis.c index 4575e271bdb030168fdb9406a5c6e937c0efb6d0..4f12ecd7634e00906f8c3c6770bf36487d49ca05 100644 --- a/src/redis.c +++ b/src/redis.c @@ -2585,6 +2585,13 @@ void redisOutOfMemoryHandler(size_t allocation_size) { redisPanic("OOM"); } +void redisSetProcTitle(char *title) { + setproctitle("%s %s:%d", + title, + server.bindaddr ? server.bindaddr : "*", + server.port); +} + int main(int argc, char **argv) { struct timeval tv; @@ -2655,6 +2662,7 @@ int main(int argc, char **argv) { if (server.daemonize) daemonize(); initServer(); if (server.daemonize) createPidFile(); + redisSetProcTitle(argv[0]); redisAsciiArt(); if (!server.sentinel_mode) { diff --git a/src/redis.h b/src/redis.h index 9a5e05a89b493673f5270de6ec36f891abc1119b..d2a6a4fb90a11ac0a87c9d102af90fabb0793175 100644 --- a/src/redis.h +++ b/src/redis.h @@ -815,6 +815,7 @@ long long mstime(void); void getRandomHexChars(char *p, unsigned int len); uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l); void exitFromChild(int retcode); +void redisSetProcTitle(char *title); /* networking.c -- Networking and Client related operations */ redisClient *createClient(int fd); diff --git a/src/setproctitle.c b/src/setproctitle.c new file mode 100644 index 0000000000000000000000000000000000000000..399205c064db46be22c39b6afed6ac8c50dc7238 --- /dev/null +++ b/src/setproctitle.c @@ -0,0 +1,259 @@ +/* ========================================================================== + * setproctitle.c - Linux/Darwin setproctitle. + * -------------------------------------------------------------------------- + * Copyright (C) 2010 William Ahern + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * ========================================================================== + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include /* NULL size_t */ +#include /* va_list va_start va_end */ +#include /* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */ +#include /* vsnprintf(3) snprintf(3) */ + +#include /* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */ + +#include /* errno program_invocation_name program_invocation_short_name */ + +#if !defined(HAVE_SETPROCTITLE) +#define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__) +#endif + + +#if !HAVE_SETPROCTITLE +#if (defined __linux || defined __APPLE__) && defined __GNUC__ + + +static struct { + /* original value */ + const char *arg0; + + /* title space available */ + char *base, *end; + + /* pointer to original nul character within base */ + char *nul; + + _Bool reset; + int error; +} SPT; + + +#ifndef SPT_MIN +#define SPT_MIN(a, b) (((a) < (b))? (a) : (b)) +#endif + +static inline size_t spt_min(size_t a, size_t b) { + return SPT_MIN(a, b); +} /* spt_min() */ + + +/* + * For discussion on the portability of the various methods, see + * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html + */ +static int spt_clearenv(void) { +#if __GLIBC__ + clearenv(); + + return 0; +#else + extern char **environ; + char **tmp; + + if (!(tmp = malloc(sizeof *tmp))) + return errno; + + tmp[0] = NULL; + environ = tmp; + + return 0; +#endif +} /* spt_clearenv() */ + + +static int spt_copyenv(char *oldenv[]) { + extern char **environ; + char *eq; + int i, error; + + if (environ != oldenv) + return 0; + + if ((error = spt_clearenv())) + goto error; + + for (i = 0; oldenv[i]; i++) { + if (!(eq = strchr(oldenv[i], '='))) + continue; + + *eq = '\0'; + error = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0; + *eq = '='; + + if (error) + goto error; + } + + return 0; +error: + environ = oldenv; + + return error; +} /* spt_copyenv() */ + + +static int spt_copyargs(int argc, char *argv[]) { + char *tmp; + int i; + + for (i = 1; i < argc || (i >= argc && argv[i]); i++) { + if (!argv[i]) + continue; + + if (!(tmp = strdup(argv[i]))) + return errno; + + argv[i] = tmp; + } + + return 0; +} /* spt_copyargs() */ + + +void spt_init(int argc, char *argv[], char *envp[]) __attribute__((constructor)); + +void spt_init(int argc, char *argv[], char *envp[]) { + char *base, *end, *nul, *tmp; + int i, error; + + if (!(base = argv[0])) + return; + + nul = &base[strlen(base)]; + end = nul + 1; + + for (i = 0; i < argc || (i >= argc && argv[i]); i++) { + if (!argv[i] || argv[i] < end) + continue; + + end = argv[i] + strlen(argv[i]) + 1; + } + + for (i = 0; envp[i]; i++) { + if (envp[i] < end) + continue; + + end = envp[i] + strlen(envp[i]) + 1; + } + + if (!(SPT.arg0 = strdup(argv[0]))) + goto syerr; + +#if __GLIBC__ + if (!(tmp = strdup(program_invocation_name))) + goto syerr; + + program_invocation_name = tmp; + + if (!(tmp = strdup(program_invocation_short_name))) + goto syerr; + + program_invocation_short_name = tmp; +#elif __APPLE__ + if (!(tmp = strdup(getprogname()))) + goto syerr; + + setprogname(tmp); +#endif + + + if ((error = spt_copyenv(envp))) + goto error; + + if ((error = spt_copyargs(argc, argv))) + goto error; + + SPT.nul = nul; + SPT.base = base; + SPT.end = end; + + return; +syerr: + error = errno; +error: + SPT.error = error; +} /* spt_init() */ + + +#ifndef SPT_MAXTITLE +#define SPT_MAXTITLE 255 +#endif + +void setproctitle(const char *fmt, ...) { + char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */ + va_list ap; + char *nul; + int len, error; + + if (!SPT.base) + return; + + if (fmt) { + va_start(ap, fmt); + len = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + } else { + len = snprintf(buf, sizeof buf, "%s", SPT.arg0); + } + + if (len <= 0) + { error = errno; goto error; } + + if (!SPT.reset) { + memset(SPT.base, 0, SPT.end - SPT.base); + SPT.reset = 1; + } else { + memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base)); + } + + len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1); + memcpy(SPT.base, buf, len); + nul = &SPT.base[len]; + + if (nul < SPT.nul) { + *SPT.nul = '.'; + } else if (nul == SPT.nul && &nul[1] < SPT.end) { + *SPT.nul = ' '; + *++nul = '\0'; + } + + return; +error: + SPT.error = error; +} /* setproctitle() */ + + +#endif /* __linux || __APPLE__ */ +#endif /* !HAVE_SETPROCTITLE */