Scheduler: Hack suppoer for ordinary files into the scheduler (epoll does *not* suppo...
[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 <algorithm>
39 #include "../Utils/Exception.hh"
40 #include "../Utils/membind.hh"
41
42 //#include "Daemon.mpp"
43 #define prefix_
44 ///////////////////////////////cc.p////////////////////////////////////////
45
46 #define LIBC_CALL(fn, args) if (fn args < 0) throwErrno(#fn "()")
47 #define LIBC_CALL_RV(var, fn, args) int var (fn args); if (var < 0) throwErrno(#fn "()")
48
49 ///////////////////////////////////////////////////////////////////////////
50 // senf::Daemon
51
52 prefix_ senf::Daemon::~Daemon()
53 {
54     if (! pidfile_.empty())
55         LIBC_CALL( ::unlink, (pidfile_.c_str()) );
56 }
57
58 prefix_ void senf::Daemon::daemonize(bool v)
59 {
60     daemonize_ = v;
61 }
62
63 prefix_ bool senf::Daemon::daemon()
64 {
65     return daemonize_;
66 }
67
68 prefix_ void senf::Daemon::consoleLog(std::string const & path, StdStream which)
69 {
70     int fd (-1);
71     if (! path.empty()) {
72         fd = ::open(path.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);
73         if (fd < 0)
74             throwErrno("::open()");
75     }
76     switch (which) {
77     case StdOut:
78         stdout_ = fd;
79         break;
80     case StdErr:
81         stderr_ = fd;
82         break;
83     case Both:
84         stdout_ = fd;
85         stderr_ = fd;
86         break;
87     }
88 }
89
90 prefix_ void senf::Daemon::pidFile(std::string const & f)
91 {
92     pidfile_ = f;
93 }
94
95 prefix_ void senf::Daemon::detach()
96 {
97     if (daemonize_) {
98         LIBC_CALL_RV( nul, ::open, ("/dev/null", O_WRONLY) );
99         LIBC_CALL( ::dup2, (stdout_ == -1 ? nul : stdout_, 1) );
100         LIBC_CALL( ::dup2, (stderr_ == -1 ? nul : stderr_, 2) );
101         LIBC_CALL( ::close, (nul) );
102
103         // We need to wait here to give the daemon watcher time to flush all data to the log file.
104         struct timespec ts;
105         ts.tv_sec = 0;
106         ts.tv_nsec = 100 * 1000000ul;
107         while (::nanosleep(&ts,&ts) < 0 && errno == EINTR) ;
108     }
109 }
110
111 prefix_ int senf::Daemon::start(int argc, char const ** argv)
112 {
113     argc_ = argc;
114     argv_ = argv;
115
116 #   ifdef NDEBUG
117
118     try {
119
120 #   endif
121
122         configure();
123
124         if (daemonize_)
125             fork();
126         if (! pidfile_.empty() && ! pidfileCreate()) {
127             std::cerr << "\n*** PID file '" << pidfile_ << "' creation failed. Daemon running ?" 
128                       << std::endl;
129             return 1;
130         }
131
132         main();
133
134 #   ifdef NDEBUG
135
136     }
137     catch (std::exception & e) {
138         std::cerr << "\n*** Fatal exception: " << e.what() << std::endl;
139         return 1;
140     }
141     catch (...) {
142         std::cerr << "\n*** Fatal exception: (unknown)" << std::endl;
143         return 1;
144     }
145
146 #   endif
147
148     return 0;
149 }
150
151 ////////////////////////////////////////
152 // protected members
153
154 prefix_ senf::Daemon::Daemon()
155     : argc_(0), argv_(0), daemonize_(true), stdout_(-1), stderr_(-1), pidfile_(""),
156       detached_(false)
157 {}
158
159 ////////////////////////////////////////
160 // private members
161
162 prefix_ void senf::Daemon::configure()
163 {}
164
165 prefix_ void senf::Daemon::main()
166 {
167     init();
168     detach();
169     run();
170 }
171
172 prefix_ void senf::Daemon::init()
173 {}
174
175 prefix_ void senf::Daemon::run()
176 {}
177
178 prefix_ void senf::Daemon::fork()
179 {
180     int coutpipe[2];
181     int cerrpipe[2];
182
183     LIBC_CALL_RV( nul, ::open, ("/dev/null", O_RDONLY) );
184     LIBC_CALL( ::dup2, (nul, 0) );
185     LIBC_CALL( ::close, (nul) );
186     LIBC_CALL( ::pipe, (coutpipe) );
187     LIBC_CALL( ::pipe, (cerrpipe) );
188
189     // We need to block the SIGCHLD signal here so we don't miss it, if the child
190     // dies immediately
191     ::sigset_t oldsig;
192     ::sigset_t cldsig;
193     ::sigemptyset(&cldsig);
194     LIBC_CALL( ::sigaddset, (&cldsig, SIGCHLD) );
195     LIBC_CALL( ::sigprocmask, (SIG_BLOCK, &cldsig, &oldsig) );
196     
197     LIBC_CALL_RV( pid, ::fork, () );
198
199     if (pid == 0) {
200         // Daemon process
201
202         LIBC_CALL( ::dup2, (coutpipe[1],1) );
203         LIBC_CALL( ::dup2, (cerrpipe[1],2) );
204         LIBC_CALL( ::close, (coutpipe[0]) );
205         LIBC_CALL( ::close, (coutpipe[1]) );
206         LIBC_CALL( ::close, (cerrpipe[0]) );
207         LIBC_CALL( ::close, (cerrpipe[1]) );
208         LIBC_CALL( ::setsid, () );
209         LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
210         return;
211     }
212
213     // Ouch ... ensure, the daemon watcher does not remove the pidfile ...
214     pidfile_ = "";
215     
216     LIBC_CALL( ::close, (coutpipe[1]) );
217     LIBC_CALL( ::close, (cerrpipe[1]) );
218
219     detail::DaemonWatcher watcher (pid, coutpipe[0], cerrpipe[0], stdout_, stderr_);
220     watcher.run();
221
222     ::_exit(0);
223 }
224
225 prefix_ bool senf::Daemon::pidfileCreate()
226 {
227     // Create temporary file pidfile_.hostname.pid and hard-link it to pidfile_ If the hardlink
228     // fails, the pidfile exists. If the link count of the temporary file is not 2 after this, there
229     // was some race condition, probably over NFS.
230
231     std::string tempname;
232
233     {
234         char hostname[HOST_NAME_MAX+1];
235         LIBC_CALL( ::gethostname, (hostname, HOST_NAME_MAX+1) );
236         hostname[HOST_NAME_MAX] = 0;
237         std::stringstream tempname_s;
238         tempname_s << pidfile_ << "." << hostname << "." << ::getpid();
239         tempname = tempname_s.str();
240     }
241
242     while (1) {
243         {
244             std::ofstream pidf (tempname.c_str());
245             pidf << ::getpid() << std::endl;
246         }
247
248         if (::link(tempname.c_str(), pidfile_.c_str()) < 0) {
249             if (errno != EEXIST) 
250                 throwErrno("::link()");
251         }
252         else {
253             struct ::stat s;
254             LIBC_CALL( ::stat, (tempname.c_str(), &s) );
255             LIBC_CALL( ::unlink, (tempname.c_str()) );
256             return s.st_nlink == 2;
257         }
258
259         // pidfile exists. Check, whether the pid in the pidfile still exists.
260         {
261             int old_pid (-1);
262             std::ifstream pidf (pidfile_.c_str());
263             if ( ! (pidf >> old_pid)
264                  || old_pid < 0 
265                  || ::kill(old_pid, 0) >= 0 
266                  || errno == EPERM )
267                 return false;
268         }
269
270         // If we reach this point, the pid file exists but the process mentioned within the
271         // pid file does *not* exists. We assume, the pid file to be stale.
272
273         // I hope, the following procedure is without race condition: We remove our generated
274         // temporary pid file and recreate it as hard-link to the old pid file. Now we check, that
275         // the hard-link count of this file is 2. If it is not, we terminate, since someone else
276         // must have already created his hardlink. We then truncate the file and write our pid.
277
278         LIBC_CALL( ::unlink, (tempname.c_str() ));
279         if (::link(pidfile_.c_str(), tempname.c_str()) < 0) {
280             if (errno != ENOENT) throwErrno("::link()");
281             // Hmm ... the pidfile mysteriously disappeared ... try again.
282             continue;
283         }
284
285         {
286             struct ::stat s;
287             LIBC_CALL( ::stat, (tempname.c_str(), &s) );
288             if (s.st_nlink != 2) {
289                 LIBC_CALL( ::unlink, (tempname.c_str()) );
290                 return false;
291             }
292         }
293         
294         {
295             std::ofstream pidf (tempname.c_str());
296             pidf << ::getpid() << std::endl;
297         }
298
299         LIBC_CALL( ::unlink, (tempname.c_str()) );
300         break;
301     }
302     return true;
303 }
304
305 ///////////////////////////////////////////////////////////////////////////
306 // senf::detail::DaemonWatcher
307
308 prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int cerrpipe,
309                                                    int stdout, int stderr)
310     : childPid_(pid), coutpipe_(coutpipe), cerrpipe_(cerrpipe), stdout_(stdout),
311       stderr_(stderr), sigChld_(false),
312       coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)), 
313       cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2)) 
314 {
315     coutForwarder_.addTarget(1);
316     if (stdout_ >= 0)
317         coutForwarder_.addTarget(stdout_);
318     cerrForwarder_.addTarget(2);
319     if (stderr_ >= 0)
320         cerrForwarder_.addTarget(stderr_);
321 }
322
323 prefix_ void senf::detail::DaemonWatcher::run()
324 {
325     Scheduler::instance().registerSignal(SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this));
326     Scheduler::instance().process();
327 }
328
329 ////////////////////////////////////////
330 // private members
331
332 prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
333 {
334     switch (id) {
335     case 1 : coutpipe_ = -1; break;
336     case 2 : cerrpipe_ = -1; break;
337     }
338
339     if (coutpipe_ == -1 && cerrpipe_ == -1) {
340         if (sigChld_)
341             childDied(); // does not return
342         Scheduler::instance().timeout(
343             Scheduler::instance().eventTime() + ClockService::seconds(1),
344             senf::membind(&DaemonWatcher::childOk, this));
345     }
346 }
347
348 prefix_ void senf::detail::DaemonWatcher::sigChld()
349 {
350     sigChld_ = true;
351     if (coutpipe_ == -1 && cerrpipe_ == -1)
352         childDied(); // does not return
353 }
354
355 prefix_ void senf::detail::DaemonWatcher::childDied()
356 {
357     int status (0);
358     if (::waitpid(childPid_,&status,0) < 0) throwErrno("::waitpid()");
359     if (WIFSIGNALED(status)) {
360         ::signal(WTERMSIG(status),SIG_DFL);
361         ::kill(::getpid(), WTERMSIG(status));
362         // should not be reached
363         ::_exit(1);
364     }
365     if (WEXITSTATUS(status) == 0)
366         ::_exit(1);
367     ::_exit(WEXITSTATUS(status));
368 }
369
370 prefix_ void senf::detail::DaemonWatcher::childOk()
371 {
372     Scheduler::instance().terminate();
373 }
374
375 ///////////////////////////////////////////////////////////////////////////
376 // senf::detail::DaemonWatcher::Forwarder
377
378 prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
379     : src_(src), cb_(cb)
380 {
381     Scheduler::instance().add(src_, senf::membind(&Forwarder::readData, this),
382                               Scheduler::EV_READ);
383 }
384
385 prefix_ senf::detail::DaemonWatcher::Forwarder::~Forwarder()
386 {
387     if (src_ != -1)
388         Scheduler::instance().remove(src_);
389     
390     for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
391         if (i->offset >= buffer_.size())
392             Scheduler::instance().remove(i->fd);
393 }
394
395 prefix_ void senf::detail::DaemonWatcher::Forwarder::addTarget(int fd)
396 {
397     Target target = { fd, 0 };
398     targets_.push_back(target);
399 }
400
401 prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(Scheduler::EventId event)
402 {
403     char buf[1024];
404     int n (0);
405
406     while (1) {
407         n = ::read(src_,buf,1024);
408         if (n<0) {
409             if (errno != EINTR) throwErrno("::read()");
410         } else 
411             break;
412     }
413
414     if (n == 0) {
415         // Hangup
416         Scheduler::instance().remove(src_);
417         if (buffer_.empty())
418             cb_(); 
419         src_ = -1;
420         return;
421     }
422
423     if (targets_.empty())
424         return;
425
426     for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
427         if (i->offset >= buffer_.size())
428             Scheduler::instance().add( i->fd, 
429                                        boost::bind(&Forwarder::writeData, this, _1, i),
430                                        Scheduler::EV_WRITE );
431
432     buffer_.insert(buffer_.end(), buf, buf+n);
433 }
434
435 prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(Scheduler::EventId event,
436                                                                Targets::iterator target)
437 {    
438     if (event != Scheduler::EV_WRITE) {
439         // Broken pipe while writing data ? Not much, we can do here, we just drop the data
440         Scheduler::instance().remove(target->fd);
441         targets_.erase(target);
442         if (targets_.empty() && src_ == -1)
443             cb_();
444         return;
445     }
446
447     char buf[1024];
448     int n (buffer_.size() - target->offset > 1024 ? 1024 : buffer_.size() - target->offset);
449     std::copy(buffer_.begin() + target->offset, buffer_.begin() + target->offset + n, buf);
450
451     int w (::write(target->fd, buf, n));
452     if (w < 0) {
453         if (errno != EINTR) throwErrno("::write()");
454         return;
455     }
456     target->offset += w;
457
458     n = std::min_element(
459         targets_.begin(), targets_.end(),
460         boost::bind(&Target::offset, _1) < boost::bind(&Target::offset, _2))->offset;
461
462     buffer_.erase(buffer_.begin(), buffer_.begin()+n);
463
464     for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
465         i->offset -= n;
466
467     if (target->offset >= buffer_.size())
468         Scheduler::instance().remove(target->fd);
469     if (src_ == -1 && (buffer_.empty() || targets_.empty()))
470         cb_();
471 }
472
473 #undef LIBC_CALL
474 #undef LIBC_CALL_RV
475
476 ///////////////////////////////cc.e////////////////////////////////////////
477 #undef prefix_
478 //#include "Daemon.mpp"
479
480 \f
481 // Local Variables:
482 // mode: c++
483 // fill-column: 100
484 // comment-column: 40
485 // c-file-style: "senf"
486 // indent-tabs-mode: nil
487 // ispell-local-dictionary: "american"
488 // compile-command: "scons -u test"
489 // End: