1 karl 1.8 //%2006////////////////////////////////////////////////////////////////////////
|
2 h.sterling 1.1 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.8 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 h.sterling 1.1 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
|
33 kumpf 1.14
|
34 h.sterling 1.1 #include <fcntl.h>
35 #include <unistd.h>
|
36 kumpf 1.14
|
37 h.sterling 1.1 #include <Pegasus/Common/Signal.h>
|
38 kumpf 1.16 #include <Pegasus/Common/Executor.h>
|
39 kumpf 1.19 #include <Pegasus/Common/AtomicInt.h>
40 #include <Pegasus/Common/Thread.h>
41 #include <Pegasus/Common/Threads.h>
|
42 kumpf 1.14
|
43 w.otsuka 1.4 #define MAX_WAIT_TIME 240
|
44 h.sterling 1.1
45 PEGASUS_USING_PEGASUS;
46 PEGASUS_USING_STD;
47
48 Boolean handleSigUsr1 = false;
49 Boolean graveError = false;
50
51 void sigUsr1Handler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
52 {
53 handleSigUsr1 = true;
54 }
55
56 void sigTermHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
57 {
58 graveError= handleSigUsr1=true;
|
59 kumpf 1.17 }
|
60 h.sterling 1.1
61
|
62 kumpf 1.19 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
63 /**
64 Indicates whether the Executor has been instructed to daemonize or
65 otherwise exit.
66 */
67 static AtomicInt _hasDaemonized(0);
68
69 /**
70 A watchdog thread that used to allow the server start-up command to
71 time out and return control even if the server initialization is not
72 complete.
73 */
74 static Thread* _waitForDaemonizationThread = 0;
75
76 /**
77 Wait for server start-up to complete. If the MAX_WAIT_TIME elapses
78 before the Executor is instructed to daemonize, then initiate the
79 daemonization. This is necessary to prevent a server start-up hang
80 from hanging the cimserver command.
81 */
82 static ThreadReturnType PEGASUS_THREAD_CDECL _waitForDaemonization(void* parm)
83 kumpf 1.19 {
84 Thread *myself = reinterpret_cast<Thread *>(parm);
85 AtomicInt* hasDaemonized = reinterpret_cast<AtomicInt*>(myself->get_parm());
86
87 Uint32 waitTimeMsec = MAX_WAIT_TIME * 1000;
88
89 while (!hasDaemonized->get() && waitTimeMsec > 0)
90 {
91 Threads::sleep(100);
92 waitTimeMsec -= 100;
93 }
94
95 if (!hasDaemonized->get())
96 {
97 MessageLoaderParms parms(
98 "src.Service.ServerProcessUnix.CIMSERVER_START_TIMEOUT",
99 "The cimserver command timed out waiting for the CIM server "
100 "to start.");
101 PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) <<
102 PEGASUS_STD(endl);
103 *hasDaemonized = 1;
104 kumpf 1.19 Executor::daemonizeExecutor();
105 }
106
107 myself->exit_self((ThreadReturnType)1);
108 return 0;
109 }
110 #endif
111
112
|
113 h.sterling 1.1 //constructor
114 ServerProcess::ServerProcess() {}
115
116 //destructor
117 ServerProcess::~ServerProcess() {}
118
119 // no-ops
120 void ServerProcess::cimserver_set_process(void* p) {}
121 void ServerProcess::cimserver_exitRC(int rc) {}
|
122 kumpf 1.17 int ServerProcess::cimserver_initialize() { return 1; }
|
123 marek 1.10
124 // for all OSes supporting signals provide a cimserver_wait function
125 // that waits to be awakened by signal PEGASUS_SIGTERM or PEGASUS_SIGHUP
126 #ifdef PEGASUS_HAS_SIGNALS
|
127 kumpf 1.17 int ServerProcess::cimserver_wait()
|
128 marek 1.10 {
129 int sig = -1;
130 sigset_t set;
131 sigemptyset(&set);
132 sigaddset(&set, PEGASUS_SIGTERM);
133 sigaddset(&set, PEGASUS_SIGHUP);
134 errno = 0;
135 do
136 {
137 #if defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_SOLARIS)
138 sig = sigwait(&set);
139 #else // else for platforms = LINUX, HPUX, AIX
140 sigwait(&set, &sig);
141 #endif
142 } while (errno == EINTR);
143 return sig;
144 }
145 #else
|
146 kumpf 1.17 int ServerProcess::cimserver_wait() { return 1; }
|
147 marek 1.10 #endif
148
|
149 kumpf 1.17 String ServerProcess::getHome() { return String::EMPTY; }
|
150 h.sterling 1.1
151 // daemon_init , RW Stevens, "Advance UNIX Programming"
152
|
153 kumpf 1.17 int ServerProcess::cimserver_fork()
154 {
|
155 kumpf 1.15 getSigHandle()->registerHandler(SIGTERM, sigTermHandler);
156 getSigHandle()->activate(SIGTERM);
157 umask(S_IRWXG | S_IRWXO);
158
|
159 kumpf 1.19 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
|
160 kumpf 1.16 if (Executor::detectExecutor() == 0)
161 {
162 // We don't need to fork if we're running with Privilege Separation
|
163 kumpf 1.18 setsid();
|
164 kumpf 1.19
165 _waitForDaemonizationThread = new Thread(
166 _waitForDaemonization, &_hasDaemonized, false);
167 if (_waitForDaemonizationThread->run() != PEGASUS_THREAD_OK)
168 {
169 // Unable to start watchdog thread.
170 delete _waitForDaemonizationThread;
171 _waitForDaemonizationThread = 0;
172 }
173
|
174 kumpf 1.16 return 0;
175 }
|
176 kumpf 1.19 #endif
|
177 kumpf 1.15
|
178 h.sterling 1.1 getSigHandle()->registerHandler(PEGASUS_SIGUSR1, sigUsr1Handler);
179 getSigHandle()->activate(PEGASUS_SIGUSR1);
|
180 kumpf 1.17
181 pid_t pid;
182 if( (pid = fork() ) < 0)
183 {
184 getSigHandle()->deactivate(PEGASUS_SIGUSR1);
185 getSigHandle()->deactivate(SIGTERM);
186 return -1;
187 }
188 else if (pid != 0)
189 {
190 //
191 // parent wait for child
192 // if there is a problem with signal, parent process terminates
193 // when waitTime expires
194 //
195 Uint32 waitTime = MAX_WAIT_TIME;
196
197 while (!handleSigUsr1 && waitTime > 0)
|
198 w.otsuka 1.4 {
|
199 kumpf 1.17 sleep(1);
200 waitTime--;
201 }
202
203 if (!handleSigUsr1)
204 {
205 MessageLoaderParms parms(
206 "src.Service.ServerProcessUnix.CIMSERVER_START_TIMEOUT",
207 "The cimserver command timed out waiting for the CIM server "
208 "to start.");
209 PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) <<
210 PEGASUS_STD(endl);
211 }
212 exit(graveError);
213 }
214
215 setsid();
216 umask(S_IRWXG | S_IRWXO);
217
218 // spawned daemon process doesn't need the old signal handlers of its parent
219 getSigHandle()->deactivate(PEGASUS_SIGUSR1);
220 kumpf 1.17 getSigHandle()->deactivate(SIGTERM);
|
221 h.sterling 1.1
|
222 kumpf 1.17 return 0;
|
223 h.sterling 1.1 }
224
225
226 // notify parent process to terminate so user knows that cimserver
227 // is ready to serve CIM requests.
228 void ServerProcess::notify_parent(int id)
229 {
|
230 kumpf 1.17 pid_t ppid = getppid();
231 if (id)
|
232 kumpf 1.19 {
|
233 kumpf 1.17 kill(ppid, SIGTERM);
|
234 kumpf 1.19 }
|
235 kumpf 1.17 else
|
236 kumpf 1.19 {
237 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
238 if (Executor::detectExecutor() == 0)
239 {
240 // Note: This logic contains a race condition which may allow the
241 // Executor to daemonize twice. However, the Executor is expected
242 // to handle this condition gracefully.
243 if (!_hasDaemonized.get())
244 {
245 Executor::daemonizeExecutor();
246 }
247 }
248 else
249 #endif
250 {
251 kill(ppid, PEGASUS_SIGUSR1);
252 }
253 }
254
255 #if defined(PEGASUS_ENABLE_PRIVILEGE_SEPARATION)
256 if (_waitForDaemonizationThread)
257 kumpf 1.19 {
258 _hasDaemonized = 1;
259 delete _waitForDaemonizationThread;
260 _waitForDaemonizationThread = 0;
261 }
262 #endif
|
263 h.sterling 1.1 }
264
265
266 // Platform specific run
|
267 kumpf 1.7 int ServerProcess::platform_run(
268 int argc,
269 char** argv,
270 Boolean shutdownOption,
271 Boolean debugOutputOption)
|
272 h.sterling 1.1 {
|
273 kumpf 1.7 return cimserver_run(argc, argv, shutdownOption, debugOutputOption);
|
274 h.sterling 1.1 }
|