fgms 0.11.8
The
FlightGear MultiPlayer Server
project
daemon.cxx
Go to the documentation of this file.
1 /**
2  * @file daemon.cxx
3  * @author Oliver Schroeder
4  */
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, U$
19 //
20 // Copyright (C) 2006 Oliver Schroeder
21 //
22 
23 //////////////////////////////////////////////////////////////////////
24 //
25 // implement the class "cDaemon", which does everything necessary
26 // to become a daemon
27 //
28 //////////////////////////////////////////////////////////////////////
29 #ifndef _MSC_VER
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/wait.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <fcntl.h>
36 #include <iostream>
37 #include <cstdlib>
39 #include "daemon.hxx"
40 
41 pid_t cDaemon::PidOfDaemon; // remember who we are
42 list <pid_t> cDaemon::Children; // keep track of our children
43 
44 //////////////////////////////////////////////////////////////////////
45 /**
46  * @brief Signal Handler connected in constructor
47  * @param SigType The type of signal
48  */
49 void cDaemon::SigHandler ( int SigType )
50 {
51  if (SigType == SIGCHLD)
52  {
53  int stat;
54  pid_t childpid;
55  while ((childpid=waitpid (-1, &stat, WNOHANG)) > 0)
56  printf("Child stopped: %d\n",childpid);
57  return;
58  }
59  if (SigType == SIGPIPE)
60  {
61  pid_t childpid;
62  childpid = getpid();
63  printf("[%d] SIGPIPE received. Connection error.\n",childpid);
64  return;
65  }
66  switch (SigType)
67  {
68  case 1:cout << "killed by SIGHUP! ";
69  cout << "Hangup (POSIX)" << endl;
70  break;
71  case 2:cout << "killed by SIGINT! ";
72  cout << "Interrupt (ANSI)" << endl;
73  break;
74  case 3:cout << "killed by SIGQUIT! ";
75  cout << "Quit (POSIX)" << endl;
76  break;
77  case 4:cout << "killed by SIGILL! ";
78  cout << "Illegal instruction (ANSI)" << endl;
79  break;
80  case 5:cout << "killed by SIGTRAP! ";
81  cout << "Trace trap (POSIX)" << endl;
82  break;
83  case 6:cout << "killed by SIGABRT! ";
84  cout << "IOT trap (4.2 BSD)" << endl;
85  break;
86  case 7:cout << "killed by SIGBUS! ";
87  cout << "BUS error (4.2 BSD)" << endl;
88  break;
89  case 8:cout << "killed by SIGFPE! ";
90  cout << "Floating-point exception (ANSI)" << endl;
91  break;
92  case 9:cout << "killed by SIGKILL! ";
93  cout << "Kill, unblockable (POSIX)" << endl;
94  break;
95  case 10:cout << "killed by SIGUSR1! ";
96  cout << "User-defined signal 1 (POSIX)" << endl;
97  break;
98  case 11:cout << "killed by SIGSEGV! ";
99  cout << "Segmentation violation (ANSI)" << endl;
100  break;
101  case 12:cout << "killed by SIGUSR2! ";
102  cout << "User-defined signal 2 (POSIX)" << endl;
103  break;
104  case 13:cout << "killed by SIGPIPE! ";
105  cout << "Broken pipe (POSIX)" << endl;
106  break;
107  case 14:cout << "killed by SIGALRM! ";
108  cout << "Alarm clock (POSIX)" << endl;
109  break;
110  case 15:cout << "killed by SIGTERM! ";
111  cout << "Termination (ANSI)" << endl;
112  break;
113  case 16:cout << "killed by SIGSTKFLT! ";
114  cout << "Stack fault" << endl;
115  break;
116  case 17:cout << "killed by SIGCHLD! ";
117  cout << "Child status has changed (POSIX)" << endl;
118  break;
119  case 18:cout << "killed by SIGCONT! ";
120  cout << "Continue (POSIX)" << endl;
121  break;
122  case 19:cout << "killed by SIGSTOP! ";
123  cout << "Stop, unblockable (POSIX)" << endl;
124  break;
125  case 20: cout << "killed by SIGTSTP! ";
126  cout << "Keyboard stop (POSIX)" << endl;
127  break;
128  case 21:cout << "killed by SIGTTIN! ";
129  cout << "Background read from tty (POSIX)" << endl;
130  break;
131  case 22:cout << "killed by SIGTTOU! ";
132  cout << "Background write to tty (POSIX)" << endl;
133  break;
134  case 23:cout << "killed by SIGURG! ";
135  cout << "Urgent condition on socket (4.2 BSD)" << endl;
136  break;
137  case 24:cout << "killed by SIGXCPU! ";
138  cout << "CPU limit exceeded (4.2 BSD)" << endl;
139  break;
140  case 25:cout << "killed by SIGXFSZ! ";
141  cout << "File size limit exceeded (4.2 BSD)" << endl;
142  break;
143  case 26:cout << "killed by SIGVTALRM! ";
144  cout << "Virtual alarm clock (4.2 BSD)" << endl;
145  break;
146  case 27:cout << "killed by SIGPROF! ";
147  cout << "Profiling alarm clock (4.2 BSD)" << endl;
148  break;
149  case 28:cout << "killed by SIGWINCH! ";
150  cout << "Window size change (4.3 BSD, Sun)" << endl;
151  break;
152  case 29: cout << "killed by SIGIO! ";
153  cout << "I/O now possible (4.2 BSD)" << endl;
154  break;
155  case 30:cout << "killed by SIGPWR! ";
156  cout << "Power failure restart (System V)" << endl;
157  break;
158  default:cout << "killed by signal " << SigType << "!" << endl;
159  }
160  exit (0);
161 }
162 
163 //////////////////////////////////////////////////////////////////////
164 /**
165  * @brief Installs the signal-handler and makes ourself a daemon
166  * @retval int -1 or error, 0 for success
167  */
168 int cDaemon::Daemonize () // make us a daemon
169 {
170  pid_t pid;
171 
172  //
173  // fork to get rid of our parent
174  //
175  if ( (pid = fork ()) < 0)
176  return (-1); // something went wrong!
177  else if ( pid > 0 ) // parent-process
178  {
179  PidOfDaemon = 0;
180  exit (0); // good-bye dad!
181  }
182  //
183  // well, my child, do well!
184  //
185  PidOfDaemon = getpid();
186  SG_LOG (SG_SYSTEMS, SG_ALERT, "# My PID is " << PidOfDaemon);
187  setsid (); // become a session leader
188  // chdir ("/"); // make sure, we're not on a mounted fs
189  umask (0); // clear the file creation mode
190  return (0); // ok, that's all volks!
191 }
192 
193 //////////////////////////////////////////////////////////////////////
194 /** @brief Kill our children and ourself
195  */
197 {
198  list <pid_t>::iterator aChild;
199 
200  aChild = Children.begin ();
201  while ( aChild != Children.end () )
202  {
203  SG_LOG (SG_SYSTEMS, SG_ALERT, "cDaemon: killing child " << (*aChild));
204  if ( kill ((*aChild), SIGTERM))
205  kill ((*aChild), SIGKILL);
206  aChild++;
207  }
208  Children.clear ();
209  // exit (0);
210 }
211 
212 
213 //////////////////////////////////////////////////////////////////////
214 /** @brief Inserts the ChildsPid in the list of our Children.
215  * So we can keep track of them and kill them if necessary,
216  * e.g. the daemon dies.
217  * @param ChildsPid int with pid
218  */
219 void cDaemon::AddChild ( pid_t ChildsPid )
220 {
221  Children.push_back (ChildsPid);
222 }
223 
224 
225 //////////////////////////////////////////////////////////////////////
226 /** @brief Get the count of child processes
227  * @retval int No of child processes
228  */
230 {
231  return (Children.size ());
232 }
233 
234 
235 
236 //////////////////////////////////////////////////////////////////////
237 /** @brief Connect some signals at startup. These are connected to ::cDaemon::SigHandler
238  */
240 {
241  //
242  // catch some signals
243  //
244  signal (SIGINT,SigHandler);
245  signal (SIGHUP,SigHandler);
246  signal (SIGTERM,SigHandler);
247  signal (SIGCHLD,SigHandler);
248  signal (SIGPIPE,SigHandler);
249  PidOfDaemon = getpid();
250 }
251 
252 //////////////////////////////////////////////////////////////////////
254 {
255  // KillAllChildren ();
256 }
257 #endif // !_MSC_VER
258 
static void AddChild(pid_t ChildsPid)
Inserts the ChildsPid in the list of our Children. So we can keep track of them and kill them if nece...
Definition: daemon.cxx:219
Stream based logging mechanism.
#define SG_LOG(C, P, M)
Definition: logstream.hxx:412
cDaemon()
Connect some signals at startup. These are connected to cDaemon::SigHandler.
Definition: daemon.cxx:239
static int NumChildren()
Get the count of child processes.
Definition: daemon.cxx:229
static list< pid_t > Children
keep track of our children
Definition: daemon.hxx:49
~cDaemon()
Definition: daemon.cxx:253
Very possible impending problem.
Definition: debug_types.h:38
static pid_t childpid
Definition: server.c:1142
static int Daemonize()
Installs the signal-handler and makes ourself a daemon.
Definition: daemon.cxx:168
static pid_t pid
Definition: server.c:1142
static pid_t PidOfDaemon
remember who we are
Definition: daemon.hxx:46
static void KillAllChildren()
Kill our children and ourself.
Definition: daemon.cxx:196
static void SigHandler(int SigType)
Signal Handler connected in constructor.
Definition: daemon.cxx:49