Scheduler: Daemon class: pidfile creation
[senf.git] / Scheduler / Daemon.cc
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer NETwork research (NET)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Daemon non-inline non-template implementation */
25
26 #include "Daemon.hh"
27 #include "Daemon.ih"
28
29 // Custom includes
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/wait.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <sstream>
38 #include "../Utils/Exception.hh"
39 #include "../Utils/membind.hh"
40
41 //#include "Daemon.mpp"
42 #define prefix_
43 ///////////////////////////////cc.p////////////////////////////////////////
44
45 #define LIBC_CALL(fn, args) if (fn args < 0) throwErrno(#fn "()")
46 #define LIBC_CALL_RV(var, fn, args) int var (fn args); if (var < 0) throwErrno(#fn "()")
47
48 ///////////////////////////////////////////////////////////////////////////
49 // senf::Daemon
50
51 prefix_ senf::Daemon::~Daemon()
52 {
53     if (! pidfile_.empty())
54         LIBC_CALL( ::unlink, (pidfile_.c_str()) );
55 }
56
57 prefix_ void senf::Daemon::daemonize(bool v)
58 {
59     daemonize_ = v;
60 }
61
62 prefix_ bool senf::Daemon::daemon()
63 {
64     return daemonize_;
65 }
66
67 prefix_ void senf::Daemon::consoleLog(std::string path, StdStream which)
68 {
69     int fd (-1);
70     if (! path.empty()) {
71         int fd (::open(path.c_str(), O_WRONLY | O_APPEND));
72         if (fd < 0)
73             throwErrno("::open()");
74     }
75     switch (which) {
76     case StdOut:
77         stdout_ = fd;
78         break;
79     case StdErr:
80         stderr_ = fd;
81         break;
82     case Both:
83         stdout_ = fd;
84         stderr_ = fd;
85         break;
86     }
87 }
88
89 prefix_ void senf::Daemon::pidFile(std::string f)
90 {
91     pidfile_ = f;
92 }
93
94 prefix_ void senf::Daemon::detach()
95 {
96     if (daemonize_) {
97         LIBC_CALL_RV( nul, ::open, ("/dev/null", O_WRONLY) );
98         LIBC_CALL( ::dup2, (nul, 1) );
99         LIBC_CALL( ::dup2, (nul, 2) );
100         LIBC_CALL( ::close, (nul) );
101     }
102 }
103
104 prefix_ int senf::Daemon::start(int argc, char const ** argv)
105 {
106     argc_ = argc;
107     argv_ = argv;
108
109 #   ifdef NDEBUG
110     try {
111 #   endif
112
113         configure();
114
115         if (daemonize_)
116             fork();
117         if (! pidfile_.empty() && ! pidfileCreate()) {
118             std::cerr << "\n*** PID file '" << pidfile_ << "' creation failed. Daemon running ?" 
119                       << std::endl;
120             return 1;
121         }
122
123         main();
124
125 #   ifdef NDEBUG
126     }
127     catch (std::exception & e) {
128         std::cerr << "\n*** Fatal exception: " << e.what() << std::endl;
129         return 1;
130     }
131     catch (...) {
132         std::cerr << "\n*** Fatal exception: (unknown)" << std::endl;
133         return 1;
134     }
135 #   endif
136
137     return 0;
138 }
139
140 ////////////////////////////////////////
141 // protected members
142
143 prefix_ senf::Daemon::Daemon()
144     : argc_(0), argv_(0), daemonize_(true), stdout_(-1), stderr_(-1), pidfile_(""),
145       detached_(false)
146 {}
147
148 ////////////////////////////////////////
149 // private members
150
151 prefix_ void senf::Daemon::configure()
152 {}
153
154 prefix_ void senf::Daemon::main()
155 {
156     init();
157     detach();
158     run();
159 }
160
161 prefix_ void senf::Daemon::init()
162 {}
163
164 prefix_ void senf::Daemon::run()
165 {}
166
167 prefix_ void senf::Daemon::fork()
168 {
169     int coutpipe[2];
170     int cerrpipe[2];
171
172     LIBC_CALL_RV( nul, ::open, ("/dev/null", O_RDONLY) );
173     LIBC_CALL( ::dup2, (nul, 0) );
174     LIBC_CALL( ::close, (nul) );
175     LIBC_CALL( ::pipe, (coutpipe) );
176     LIBC_CALL( ::pipe, (cerrpipe) );
177
178     // We need to block the SIGCHLD signal here so we don't miss it, if the child
179     // dies immediately
180     ::sigset_t oldsig;
181     ::sigset_t cldsig;
182     ::sigemptyset(&cldsig);
183     LIBC_CALL( ::sigaddset, (&cldsig, SIGCHLD) );
184     LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
185     
186     LIBC_CALL_RV( pid, ::fork, () );
187
188     if (pid == 0) {
189         // Daemon process
190
191         LIBC_CALL( ::dup2, (coutpipe[1],1) );
192         LIBC_CALL( ::dup2, (cerrpipe[1],2) );
193         LIBC_CALL( ::close, (coutpipe[0]) );
194         LIBC_CALL( ::close, (coutpipe[1]) );
195         LIBC_CALL( ::close, (cerrpipe[0]) );
196         LIBC_CALL( ::close, (cerrpipe[1]) );
197         LIBC_CALL( ::setsid, () );
198         LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
199         return;
200     }
201
202     // Ouch ... ensure, the daemon watcher does not remove the pidfile ...
203     pidfile_ = "";
204     
205     LIBC_CALL( ::close, (coutpipe[1]) );
206     LIBC_CALL( ::close, (cerrpipe[1]) );
207
208     detail::DaemonWatcher watcher (pid, coutpipe[0], cerrpipe[0]);
209     watcher.run();
210
211     ::_exit(0);
212 }
213
214 prefix_ bool senf::Daemon::pidfileCreate()
215 {
216     // Create temporary file pidfile_.hostname.pid and hard-link it to pidfile_ If the hardlink
217     // fails, the pidfile exists. If the link count of the temporary file is not 2 after this, there
218     // was some race condition, probably over NFS.
219
220     std::string tempname;
221
222     {
223         char hostname[HOST_NAME_MAX+1];
224         LIBC_CALL( ::gethostname, (hostname, HOST_NAME_MAX+1) );
225         hostname[HOST_NAME_MAX] = 0;
226         std::stringstream tempname_s;
227         tempname_s << pidfile_ << "." << hostname << "." << ::getpid();
228         tempname = tempname_s.str();
229     }
230
231     while (1) {
232         {
233             std::ofstream pidf (tempname.c_str());
234             pidf << ::getpid() << std::endl;
235         }
236
237         if (::link(tempname.c_str(), pidfile_.c_str()) < 0) {
238             if (errno != EEXIST) 
239                 throwErrno("::link()");
240         }
241         else {
242             struct ::stat s;
243             LIBC_CALL( ::stat, (tempname.c_str(), &s) );
244             LIBC_CALL( ::unlink, (tempname.c_str()) );
245             return s.st_nlink == 2;
246         }
247
248         // pidfile exists. Check, whether the pid in the pidfile still exists.
249         {
250             int old_pid (-1);
251             std::ifstream pidf (pidfile_.c_str());
252             if ( ! (pidf >> old_pid)
253                  || old_pid < 0 
254                  || ::kill(old_pid, 0) >= 0 
255                  || errno == EPERM )
256                 return false;
257         }
258
259         // If we reach this point, the pid file exists but the process mentioned within the
260         // pid file does *not* exists. We assume, the pid file to be stale.
261
262         // I hope, the following procedure is without race condition: We remove our generated
263         // temporary pid file and recreate it as hard-link to the old pid file. Now we check, that
264         // the hard-link count of this file is 2. If it is not, we terminate, since someone else
265         // must have already created his hardlink. We then truncate the file and write our pid.
266
267         LIBC_CALL( ::unlink, (tempname.c_str() ));
268         if (::link(pidfile_.c_str(), tempname.c_str()) < 0) {
269             if (errno != ENOENT) throwErrno("::link()");
270             // Hmm ... the pidfile mysteriously disappeared ... try again.
271             continue;
272         }
273
274         {
275             struct ::stat s;
276             LIBC_CALL( ::stat, (tempname.c_str(), &s) );
277             if (s.st_nlink != 2) {
278                 LIBC_CALL( ::unlink, (tempname.c_str()) );
279                 return false;
280             }
281         }
282         
283         {
284             std::ofstream pidf (tempname.c_str());
285             pidf << ::getpid() << std::endl;
286         }
287
288         LIBC_CALL( ::unlink, (tempname.c_str()) );
289         break;
290     }
291     return true;
292 }
293
294 ///////////////////////////////////////////////////////////////////////////
295 // senf::detail::DaemonWatcher
296
297 prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int cerrpipe)
298     : childPid_(pid), coutpipe_(coutpipe), cerrpipe_(cerrpipe), sigChld_(false),
299       coutForwarder_(coutpipe_, 1, boost::bind(&DaemonWatcher::pipeClosed, this, 1)),
300       cerrForwarder_(cerrpipe_, 2, boost::bind(&DaemonWatcher::pipeClosed, this, 2))
301 {}
302
303 prefix_ void senf::detail::DaemonWatcher::run()
304 {
305     Scheduler::instance().registerSignal(SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this));
306     Scheduler::instance().process();
307 }
308
309 ////////////////////////////////////////
310 // private members
311
312 prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
313 {
314     switch (id) {
315     case 1 : coutpipe_ = -1; break;
316     case 2 : cerrpipe_ = -1; break;
317     }
318
319     if (coutpipe_ == -1 && cerrpipe_ == -1) {
320         if (sigChld_)
321             childDied(); // does not return
322         Scheduler::instance().timeout(
323             Scheduler::instance().eventTime() + ClockService::seconds(1),
324             senf::membind(&DaemonWatcher::childOk, this));
325     }
326 }
327
328 prefix_ void senf::detail::DaemonWatcher::sigChld()
329 {
330     sigChld_ = true;
331     if (coutpipe_ == -1 && cerrpipe_ == -1)
332         childDied(); // does not return
333 }
334
335 prefix_ void senf::detail::DaemonWatcher::childDied()
336 {
337     int status (0);
338     if (::waitpid(childPid_,&status,0) < 0) throwErrno("::waitpid()");
339     if (WIFSIGNALED(status)) {
340         ::signal(WTERMSIG(status),SIG_DFL);
341         ::kill(::getpid(), WTERMSIG(status));
342         // should not be reached
343         ::_exit(1);
344     }
345     if (WEXITSTATUS(status) == 0)
346         ::_exit(1);
347     ::_exit(WEXITSTATUS(status));
348 }
349
350 prefix_ void senf::detail::DaemonWatcher::childOk()
351 {
352     Scheduler::instance().terminate();
353 }
354
355 ///////////////////////////////////////////////////////////////////////////
356 // senf::detail::DaemonWatcher::Forwarder
357
358 prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, int dst, Callback cb)
359     : src_(src), dst_(dst), cb_(cb)
360 {
361     Scheduler::instance().add(src_, senf::membind(&Forwarder::readData, this),
362                               Scheduler::EV_READ);
363 }
364
365 prefix_ senf::detail::DaemonWatcher::Forwarder::~Forwarder()
366 {
367     if (src_ != -1)
368         Scheduler::instance().remove(src_);
369     if (dst_ != -1 && ! buffer_.empty())
370         Scheduler::instance().remove(dst_);
371 }
372
373 prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId event)
374 {
375     char buf[1024];
376     int n (0);
377     while (1) {
378         n = ::read(src_,buf,1024);
379         if (n<0) {
380             if (errno != EINTR) throwErrno("::read()");
381         } else 
382             break;
383     }
384     if (n == 0) {
385         // Hangup
386         Scheduler::instance().remove(src_);
387         if (buffer_.empty())
388             cb_(); 
389         src_ = -1;
390         return;
391     }
392     if (dst_ == -1)
393         // There was an error writing data -> drop it
394         return;
395     if (buffer_.empty())
396         Scheduler::instance().add(dst_, senf::membind(&Forwarder::writeData, this),
397                                   Scheduler::EV_WRITE);
398     buffer_.insert(buffer_.end(), buf, buf+n);
399 }
400
401 prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(Scheduler::EventId event)
402 {    
403     if (event != Scheduler::EV_WRITE) {
404         // Broken pipe while writing data ? Not much, we can do here, we just drop the data
405         Scheduler::instance().remove(dst_);
406         dst_ = -1;
407         if (src_ == -1) cb_();
408         return;
409     }
410     char buf[1024];
411     int n (buffer_.size() > 1024 ? 1024 : buffer_.size());
412     std::copy(buffer_.begin(), buffer_.begin() + n, buf);
413     int w (::write(dst_, buf, n));
414     if (w < 0) {
415         if (errno != EINTR) throwErrno("::write()");
416         return;
417     }
418     buffer_.erase(buffer_.begin(), buffer_.begin()+w);
419     if (buffer_.empty()) {
420         Scheduler::instance().remove(dst_);
421         if (src_ == -1)
422             cb_();
423     }
424 }
425
426 #undef LIBC_CALL
427 #undef LIBC_CALL_RV
428
429 ///////////////////////////////cc.e////////////////////////////////////////
430 #undef prefix_
431 //#include "Daemon.mpp"
432
433 \f
434 // Local Variables:
435 // mode: c++
436 // fill-column: 100
437 // comment-column: 40
438 // c-file-style: "senf"
439 // indent-tabs-mode: nil
440 // ispell-local-dictionary: "american"
441 // compile-command: "scons -u test"
442 // End: