-
Notifications
You must be signed in to change notification settings - Fork 504
/
Copy pathdaemon_util.h
127 lines (112 loc) · 3.42 KB
/
daemon_util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#pragma once
#include <config/config.h>
#include <glog/logging.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <cstdlib>
#include "unique_fd.h"
inline bool SupervisedUpstart() {
const char *upstart_job = getenv("UPSTART_JOB");
if (!upstart_job) {
LOG(WARNING) << "upstart supervision requested, but UPSTART_JOB not found";
return false;
}
LOG(INFO) << "supervised by upstart, will stop to signal readiness";
raise(SIGSTOP);
unsetenv("UPSTART_JOB");
return true;
}
inline bool SupervisedSystemd() {
const char *notify_socket = getenv("NOTIFY_SOCKET");
if (!notify_socket) {
LOG(WARNING) << "systemd supervision requested, but NOTIFY_SOCKET not found";
return false;
}
auto fd = UniqueFD(socket(AF_UNIX, SOCK_DGRAM, 0));
if (!fd) {
LOG(WARNING) << "Cannot connect to systemd socket " << notify_socket;
return false;
}
sockaddr_un su;
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';
iovec iov;
memset(&iov, 0, sizeof(iov));
std::string ready = "READY=1";
iov.iov_base = &ready[0];
iov.iov_len = ready.size();
msghdr hdr;
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;
int sendto_flags = 0;
unsetenv("NOTIFY_SOCKET");
#ifdef HAVE_MSG_NOSIGNAL
sendto_flags |= MSG_NOSIGNAL;
#endif
if (sendmsg(*fd, &hdr, sendto_flags) < 0) {
LOG(WARNING) << "Cannot send notification to systemd";
return false;
}
return true;
}
inline bool IsSupervisedMode(SupervisedMode mode) {
if (mode == kSupervisedAutoDetect) {
const char *upstart_job = getenv("UPSTART_JOB");
const char *notify_socket = getenv("NOTIFY_SOCKET");
if (upstart_job) {
mode = kSupervisedUpStart;
} else if (notify_socket) {
mode = kSupervisedSystemd;
}
}
if (mode == kSupervisedUpStart) {
return SupervisedUpstart();
} else if (mode == kSupervisedSystemd) {
return SupervisedSystemd();
}
return false;
}
inline void Daemonize() {
pid_t pid = fork();
if (pid < 0) {
LOG(ERROR) << "Failed to fork the process, err: " << strerror(errno);
exit(1);
}
if (pid > 0) exit(EXIT_SUCCESS); // parent process
// change the file mode
umask(0);
if (setsid() < 0) {
LOG(ERROR) << "Failed to setsid, err: %s" << strerror(errno);
exit(1);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}