-rw-r--r-- | src/process.cc | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/src/process.cc b/src/process.cc index bfab311..1ffac9f 100644 --- a/src/process.cc +++ b/src/process.cc | |||
@@ -1,80 +1,69 @@ | |||
1 | #include <stdio.h> | 1 | #include <stdio.h> |
2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
3 | #include <unistd.h> | 3 | #include <unistd.h> |
4 | #include <signal.h> | 4 | #include <signal.h> |
5 | #include <pwd.h> | 5 | #include <pwd.h> |
6 | #include <grp.h> | 6 | #include <grp.h> |
7 | #include <sys/wait.h> | 7 | #include <sys/wait.h> |
8 | #include <syslog.h> | 8 | #include <syslog.h> |
9 | #include <errno.h> | 9 | #include <errno.h> |
10 | #include <iostream> | 10 | #include <iostream> |
11 | #include <fstream> | 11 | #include <fstream> |
12 | #include <stdexcept> | 12 | #include <stdexcept> |
13 | using namespace std; | 13 | using namespace std; |
14 | #include "process.h" | 14 | #include "process.h" |
15 | #include "configuration.h" | 15 | #include "configuration.h" |
16 | 16 | ||
17 | void process::check(const string& id,configuration& config) { | 17 | void process::check(const string& id,configuration& config) { |
18 | bool running = false; | 18 | try { |
19 | ifstream pids(pidfile.c_str(),ios::in); | 19 | signal(0); |
20 | if(pids) { | ||
21 | pid_t pid = 0; | ||
22 | pids >> pid; | ||
23 | pids.close(); | ||
24 | if(pid) { | ||
25 | if(!kill(pid,0)) { | ||
26 | running = true; | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | if(running){ | ||
31 | patience = 0; | 20 | patience = 0; |
32 | }else{ | 21 | }catch(exception& e) { |
33 | if(patience>60) { // TODO: configurable | 22 | if(patience>60) { // TODO: configurable |
34 | patience = 0; | 23 | patience = 0; |
35 | }else{ | 24 | }else{ |
36 | if(patience<10) { // TODO: configurable | 25 | if(patience<10) { // TODO: configurable |
37 | syslog(LOG_NOTICE,"The process '%s' is down, trying to launch.",id.c_str()); | 26 | syslog(LOG_NOTICE,"The process '%s' is down, trying to launch.",id.c_str()); |
38 | do_notify(id,"Starting up", | 27 | do_notify(id,"Starting up", |
39 | "The named process seems to be down. Dudki will try\n" | 28 | "The named process seems to be down. Dudki will try\n" |
40 | "to revive it by running the specified command.\n", | 29 | "to revive it by running the specified command.\n", |
41 | config); | 30 | config); |
42 | try { | 31 | try { |
43 | launch(id,config); | 32 | launch(id,config); |
44 | }catch(exception& e) { | 33 | }catch(exception& e) { |
45 | syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); | 34 | syslog(LOG_ERR,"Error trying to launch process '%s': %s",id.c_str(),e.what()); |
46 | } | 35 | } |
47 | }else if(patience==10){ // TODO: configurable like the above | 36 | }else if(patience==10){ // TODO: configurable like the above |
48 | syslog(LOG_NOTICE,"Giving up on process '%s' for a while",id.c_str()); | 37 | syslog(LOG_NOTICE,"Giving up on process '%s' for a while",id.c_str()); |
49 | do_notify(id,"Giving up", | 38 | do_notify(id,"Giving up", |
50 | "After a number of attempts to relaunch the named process\n" | 39 | "After a number of attempts to relaunch the named process\n" |
51 | "It still seems to be down. Dudki is giving up attempts\n" | 40 | "It still seems to be down. Dudki is giving up attempts\n" |
52 | "to revive the process for a while.\n", | 41 | "to revive the process for a while.\n", |
53 | config); | 42 | config); |
54 | } | 43 | } |
55 | patience++; | 44 | patience++; |
56 | } | 45 | } |
57 | } | 46 | } |
58 | } | 47 | } |
59 | 48 | ||
60 | void process::launch(const string& id,configuration& config) { | 49 | void process::launch(const string& id,configuration& config) { |
61 | uid_t uid = (uid_t)-1; | 50 | uid_t uid = (uid_t)-1; |
62 | gid_t gid = (gid_t)-1; | 51 | gid_t gid = (gid_t)-1; |
63 | if(!user.empty()) { | 52 | if(!user.empty()) { |
64 | struct passwd *ptmp = getpwnam(user.c_str()); | 53 | struct passwd *ptmp = getpwnam(user.c_str()); |
65 | if(ptmp) { | 54 | if(ptmp) { |
66 | uid = ptmp->pw_uid; | 55 | uid = ptmp->pw_uid; |
67 | gid = ptmp->pw_gid; | 56 | gid = ptmp->pw_gid; |
68 | }else{ | 57 | }else{ |
69 | errno=0; | 58 | errno=0; |
70 | uid = strtol(user.c_str(),NULL,0); | 59 | uid = strtol(user.c_str(),NULL,0); |
71 | if(errno) | 60 | if(errno) |
72 | throw runtime_error("Failed to resolve User value to uid"); | 61 | throw runtime_error("Failed to resolve User value to uid"); |
73 | } | 62 | } |
74 | } | 63 | } |
75 | if(!group.empty()) { | 64 | if(!group.empty()) { |
76 | struct group *gtmp = getgrnam(group.c_str()); | 65 | struct group *gtmp = getgrnam(group.c_str()); |
77 | if(gtmp) { | 66 | if(gtmp) { |
78 | gid = gtmp->gr_gid; | 67 | gid = gtmp->gr_gid; |
79 | }else{ | 68 | }else{ |
80 | errno = 0; | 69 | errno = 0; |
@@ -140,48 +129,61 @@ void process::do_notify(const string& id,const string& event,const string& descr | |||
140 | }catch(exception& e) { | 129 | }catch(exception& e) { |
141 | syslog(LOG_ERR,"Notification error: %s",e.what()); | 130 | syslog(LOG_ERR,"Notification error: %s",e.what()); |
142 | } | 131 | } |
143 | } | 132 | } |
144 | 133 | ||
145 | void process::notify_mailto(const string& email,const string& id,const string& event,const string& description,configuration& config) { | 134 | void process::notify_mailto(const string& email,const string& id,const string& event,const string& description,configuration& config) { |
146 | int files[2]; | 135 | int files[2]; |
147 | if(pipe(files)) | 136 | if(pipe(files)) |
148 | throw runtime_error("Failed to pipe()"); | 137 | throw runtime_error("Failed to pipe()"); |
149 | pid_t pid = vfork(); | 138 | pid_t pid = vfork(); |
150 | if(pid==-1) { | 139 | if(pid==-1) { |
151 | close(files[0]); | 140 | close(files[0]); |
152 | close(files[1]); | 141 | close(files[1]); |
153 | throw runtime_error("Failed to vfork()"); | 142 | throw runtime_error("Failed to vfork()"); |
154 | } | 143 | } |
155 | if(!pid) { | 144 | if(!pid) { |
156 | // child | 145 | // child |
157 | if(dup2(files[0],0)!=0) | 146 | if(dup2(files[0],0)!=0) |
158 | _exit(-1); | 147 | _exit(-1); |
159 | close(1); | 148 | close(1); |
160 | close(files[0]); | 149 | close(files[0]); |
161 | close(files[1]); | 150 | close(files[1]); |
162 | execl("/usr/sbin/sendmail","usr/sbin/sendmail","-i",email.c_str(),NULL); | 151 | execl("/usr/sbin/sendmail","usr/sbin/sendmail","-i",email.c_str(),NULL); |
163 | _exit(-1); | 152 | _exit(-1); |
164 | } | 153 | } |
165 | // parent | 154 | // parent |
166 | close(files[0]); | 155 | close(files[0]); |
167 | FILE *mta = fdopen(files[1],"w"); | 156 | FILE *mta = fdopen(files[1],"w"); |
168 | for(headers_t::const_iterator i=mailto_headers.begin();i!=mailto_headers.end();++i) { | 157 | for(headers_t::const_iterator i=mailto_headers.begin();i!=mailto_headers.end();++i) { |
169 | fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); | 158 | fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); |
170 | } | 159 | } |
171 | for(headers_t::const_iterator i=config.mailto_headers.begin();i!=config.mailto_headers.end();++i) { | 160 | for(headers_t::const_iterator i=config.mailto_headers.begin();i!=config.mailto_headers.end();++i) { |
172 | if(mailto_headers.find(i->first)!=mailto_headers.end()) | 161 | if(mailto_headers.find(i->first)!=mailto_headers.end()) |
173 | continue; | 162 | continue; |
174 | fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); | 163 | fprintf(mta,"%s: %s\n",i->first.c_str(),i->second.c_str()); |
175 | } | 164 | } |
176 | fprintf(mta, | 165 | fprintf(mta, |
177 | "Subject: [%s] %s\n\n" | 166 | "Subject: [%s] %s\n\n" |
178 | "%s\n" | 167 | "%s\n" |
179 | "---\n" | 168 | "---\n" |
180 | "This message was sent automatically by the 'dudki' daemon\n", | 169 | "This message was sent automatically by the 'dudki' daemon\n", |
181 | id.c_str(), event.c_str(), | 170 | id.c_str(), event.c_str(), |
182 | description.c_str() ); | 171 | description.c_str() ); |
183 | fclose(mta); | 172 | fclose(mta); |
184 | int status; | 173 | int status; |
185 | waitpid(pid,&status,0); | 174 | waitpid(pid,&status,0); |
186 | // TODO: check the return code | 175 | // TODO: check the return code |
187 | } | 176 | } |
177 | |||
178 | void process::signal(int signum) const { | ||
179 | ifstream pids(pidfile.c_str(),ios::in); | ||
180 | if(!pids) | ||
181 | throw runtime_error("no pidfile found"); | ||
182 | pid_t pid = 0; | ||
183 | pids >> pid; | ||
184 | pids.close(); | ||
185 | if(!pid) | ||
186 | throw runtime_error("no pid in pidfile"); | ||
187 | if(kill(pid,signum)) | ||
188 | throw runtime_error("failed to signal process"); | ||
189 | } | ||