(file) Return to ServerProcessUnix.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Service

  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  }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2