diff options
author | Johannes Truschnigg <johannes@truschnigg.info> | 2019-04-27 18:07:30 +0200 |
---|---|---|
committer | max ulidtko <ulidtko@gmail.com> | 2019-11-19 18:55:44 +0200 |
commit | 641c64ada10404356fc76c0b56a69b32c76f253c (patch) | |
tree | a1310ebd0116c69bd3953afcc8590ceb1a52835a /src | |
parent | 45025713a8b284d649af540c0cab2e5af52e1a9f (diff) | |
download | redis-641c64ada10404356fc76c0b56a69b32c76f253c.tar.gz |
Use libsystemd's sd_notify for communicating redis status to systemd
Instead of replicating a subset of libsystemd's sd_notify(3) internally,
use the dynamic library provided by systemd to communicate with the
service manager.
When systemd supervision was auto-detected or configured, communicate
the actual server status (i.e. "Loading dataset", "Waiting for
master<->replica sync") to systemd, instead of declaring readiness right
after initializing the server process.
Diffstat (limited to 'src')
-rw-r--r-- | src/replication.c | 5 | ||||
-rw-r--r-- | src/server.c | 84 | ||||
-rw-r--r-- | src/server.h | 1 |
3 files changed, 48 insertions, 42 deletions
diff --git a/src/replication.c b/src/replication.c index c9a2e0fe1..68dc77a61 100644 --- a/src/replication.c +++ b/src/replication.c @@ -1665,6 +1665,11 @@ void readSyncBulkPayload(connection *conn) { if (server.repl_backlog == NULL) createReplicationBacklog(); serverLog(LL_NOTICE, "MASTER <-> REPLICA sync: Finished with success"); + if (server.supervised_mode == SUPERVISED_SYSTEMD) { + redisCommunicateSystemd("STATUS=MASTER <-> REPLICA sync: Finished with success. Ready to accept connections.\n"); + redisCommunicateSystemd("READY=1\n"); + } + /* Restart the AOF subsystem now that we finished the sync. This * will trigger an AOF rewrite, and when done will start appending * to the new file. */ diff --git a/src/server.c b/src/server.c index 2e9a329dd..e86f16aa8 100644 --- a/src/server.c +++ b/src/server.c @@ -55,6 +55,7 @@ #include <sys/utsname.h> #include <locale.h> #include <sys/socket.h> +#include <dlfcn.h> /* Our shared "common" objects */ @@ -3651,6 +3652,8 @@ int prepareForShutdown(int flags) { int nosave = flags & SHUTDOWN_NOSAVE; serverLog(LL_WARNING,"User requested shutdown..."); + if (server.supervised_mode == SUPERVISED_SYSTEMD) + redisCommunicateSystemd("STOPPING=1\n"); /* Kill all the Lua debugger forked sessions. */ ldbKillForkedSessions(); @@ -3692,6 +3695,8 @@ int prepareForShutdown(int flags) { /* Create a new RDB file before exiting. */ if ((server.saveparamslen > 0 && !nosave) || save) { serverLog(LL_NOTICE,"Saving the final RDB snapshot before exiting."); + if (server.supervised_mode == SUPERVISED_SYSTEMD) + redisCommunicateSystemd("STATUS=Saving the final RDB snapshot\n"); /* Snapshotting. Perform a SYNC SAVE and exit */ rdbSaveInfo rsi, *rsiptr; rsiptr = rdbPopulateSaveInfo(&rsi); @@ -3702,6 +3707,8 @@ int prepareForShutdown(int flags) { * saving aborted, handling special stuff like slaves pending for * synchronization... */ serverLog(LL_WARNING,"Error trying to save the DB, can't exit."); + if (server.supervised_mode == SUPERVISED_SYSTEMD) + redisCommunicateSystemd("STATUS=Error trying to save the DB, can't exit.\n"); return C_ERR; } } @@ -4867,13 +4874,11 @@ int redisSupervisedUpstart(void) { return 1; } -int redisSupervisedSystemd(void) { +int redisCommunicateSystemd(const char *sd_notify_msg) { const char *notify_socket = getenv("NOTIFY_SOCKET"); - int fd = 1; - struct sockaddr_un su; - struct iovec iov; - struct msghdr hdr; - int sendto_flags = 0; + int (*dl_sd_notify)(int unset_environment, const char *state); + char *error; + void *handle; if (!notify_socket) { serverLog(LL_WARNING, @@ -4881,47 +4886,28 @@ int redisSupervisedSystemd(void) { return 0; } - if ((strchr("@/", notify_socket[0])) == NULL || strlen(notify_socket) < 2) { - return 0; - } - - serverLog(LL_NOTICE, "supervised by systemd, will signal readiness"); - if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) { + handle = dlopen("libsystemd.so.0", RTLD_LAZY); + if (!handle) { serverLog(LL_WARNING, - "Can't connect to systemd socket %s", notify_socket); + "systemd supervision requested, but could not dlopen() libsystemd.so"); + (void) dlerror(); return 0; } + (void) dlerror(); - memset(&su, 0, sizeof(su)); - su.sun_family = AF_UNIX; - strncpy (su.sun_path, notify_socket, sizeof(su.sun_path) -1); - su.sun_path[sizeof(su.sun_path) - 1] = '\0'; - - if (notify_socket[0] == '@') - su.sun_path[0] = '\0'; + *(void **)(&dl_sd_notify) = dlsym(handle, "sd_notify"); + error = dlerror(); - memset(&iov, 0, sizeof(iov)); - iov.iov_base = "READY=1"; - iov.iov_len = strlen("READY=1"); - - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_name = &su; - hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + - strlen(notify_socket); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - - unsetenv("NOTIFY_SOCKET"); -#ifdef HAVE_MSG_NOSIGNAL - sendto_flags |= MSG_NOSIGNAL; -#endif - if (sendmsg(fd, &hdr, sendto_flags) < 0) { - serverLog(LL_WARNING, "Can't send notification to systemd"); - close(fd); + if (error != NULL) { + serverLog(LL_WARNING, + "systemd supervision requested, but could not load sd_notify(3) from libsystemd.so"); + dlclose(handle); return 0; } - close(fd); - return 1; + + (void) (*dl_sd_notify)(0, sd_notify_msg); + dlclose(handle); + return 0; } int redisIsSupervised(int mode) { @@ -4932,12 +4918,17 @@ int redisIsSupervised(int mode) { if (upstart_job) { redisSupervisedUpstart(); } else if (notify_socket) { - redisSupervisedSystemd(); + server.supervised_mode = SUPERVISED_SYSTEMD; + serverLog(LL_WARNING, + "WARNING auto-supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit."); + return redisCommunicateSystemd("STATUS=Redis is loading...\n"); } } else if (mode == SUPERVISED_UPSTART) { return redisSupervisedUpstart(); } else if (mode == SUPERVISED_SYSTEMD) { - return redisSupervisedSystemd(); + serverLog(LL_WARNING, + "WARNING supervised by systemd - you MUST set appropriate values for TimeoutStartSec and TimeoutStopSec in your service unit."); + return redisCommunicateSystemd("STATUS=Redis is loading...\n"); } return 0; @@ -5130,6 +5121,15 @@ int main(int argc, char **argv) { serverLog(LL_NOTICE,"Ready to accept connections"); if (server.sofd > 0) serverLog(LL_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket); + if (server.supervised_mode == SUPERVISED_SYSTEMD) { + /* XXX TODO is this sufficient to pass readiness control off to readSyncBulkPayload()? */ + if (!server.masterhost) { + redisCommunicateSystemd("STATUS=Ready to accept connections\n"); + redisCommunicateSystemd("READY=1\n"); + } else { + redisCommunicateSystemd("STATUS=Waiting for MASTER <-> REPLICA sync\n"); + } + } } else { InitServerLast(); sentinelIsRunning(); diff --git a/src/server.h b/src/server.h index ad47fe80b..28aa2085c 100644 --- a/src/server.h +++ b/src/server.h @@ -1620,6 +1620,7 @@ uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l); void exitFromChild(int retcode); size_t redisPopcount(void *s, long count); void redisSetProcTitle(char *title); +int redisCommunicateSystemd(const char *sd_notify_msg); /* networking.c -- Networking and Client related operations */ client *createClient(connection *conn); |