(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                // Author: Mike Day (mdday@us.ibm.com)
 33                //
 34 h.sterling 1.1 // Modified By:  Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
 35                //       Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
 36                //       Marek Szermutzky, IBM (ddt6szer@de.ibm.com)
 37                //%/////////////////////////////////////////////////////////////////////////////
 38                #include <sys/types.h>
 39                #include <sys/stat.h>
 40                #if defined(PEGASUS_OS_HPUX)
 41                #include <sys/pstat.h>
 42 mateus.baur 1.11.18.1 #include <libgen.h>
 43 h.sterling  1.1       #endif
 44                       #include <fcntl.h>
 45                       #include <unistd.h>
 46                       #include <Pegasus/Common/Signal.h>
 47 mike        1.11      #include <Pegasus/Common/AutoPtr.h>
 48 h.sterling  1.1       #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
 49                       #include <sys/ps.h>
 50                       #endif
 51 w.otsuka    1.4       #define MAX_WAIT_TIME 240
 52 h.sterling  1.1       #if defined(PEGASUS_OS_AIX)
 53                       #include <procinfo.h>
 54                       #define PROCSIZE sizeof(struct procsinfo)
 55 dave.sudlik 1.11.18.3 #if PEGASUS_AIX_VERSION <= 5
 56                       // AIX version 5 does not define getprocs() in procinfo.h
 57                       extern "C" {
 58                       extern int getprocs(struct procsinfo *, int, struct fdsinfo *, int,pid_t *,int);
 59 h.sterling  1.1       }
 60                       #endif
 61 dave.sudlik 1.11.18.3 #endif
 62 h.sterling  1.1       
 63                       PEGASUS_USING_PEGASUS;
 64                       PEGASUS_USING_STD;
 65                       
 66                       Boolean handleSigUsr1 = false;
 67                       Boolean graveError = false;
 68                       
 69 r.kieninger 1.9       // the current pid is the server pid. After fork it is overwritten.
 70                       pid_t server_pid = getpid();
 71 h.sterling  1.3       Uint32 parentPid = 0;
 72 h.sterling  1.1       
 73                       void sigUsr1Handler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
 74                       {
 75                           handleSigUsr1 = true;
 76                       }
 77                       
 78                       void sigTermHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
 79                       {
 80                           graveError= handleSigUsr1=true;
 81                       } 
 82                       
 83                       
 84                       //constructor
 85                       ServerProcess::ServerProcess() {}
 86                       
 87                       //destructor
 88                       ServerProcess::~ServerProcess() {}
 89                       
 90                       // no-ops
 91                       void ServerProcess::cimserver_set_process(void* p) {}
 92                       void ServerProcess::cimserver_exitRC(int rc) {}
 93 h.sterling  1.1       int ServerProcess::cimserver_initialize(void) { return 1; }
 94 marek       1.10      
 95                       // for all OSes supporting signals provide a cimserver_wait function
 96                       // that waits to be awakened by signal PEGASUS_SIGTERM or PEGASUS_SIGHUP
 97                       #ifdef PEGASUS_HAS_SIGNALS
 98                       int ServerProcess::cimserver_wait(void)
 99                       {
100                           int sig = -1;
101                           sigset_t set;
102                           sigemptyset(&set);
103                           sigaddset(&set, PEGASUS_SIGTERM);
104                           sigaddset(&set, PEGASUS_SIGHUP);
105                           errno = 0;
106                           do
107                           {
108                       #if defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_SOLARIS)
109                               sig = sigwait(&set);
110                       #else // else for platforms = LINUX, HPUX, AIX
111                               sigwait(&set, &sig);
112                       #endif
113                           } while (errno == EINTR);
114                           return sig;
115 marek       1.10      }
116                       #else
117 h.sterling  1.1       int ServerProcess::cimserver_wait(void) { return 1; }
118 marek       1.10      #endif
119                       
120 h.sterling  1.1       String ServerProcess::getHome(void) { return String::EMPTY; }
121                       
122                       // daemon_init , RW Stevens, "Advance UNIX Programming"
123                       
124                       int ServerProcess::cimserver_fork(void) 
125                       { 
126                           getSigHandle()->registerHandler(PEGASUS_SIGUSR1, sigUsr1Handler);
127                           getSigHandle()->activate(PEGASUS_SIGUSR1);
128                           getSigHandle()->registerHandler(SIGTERM, sigTermHandler);
129                           getSigHandle()->activate(SIGTERM);
130                        
131                         pid_t pid;
132                         if( (pid = fork() ) < 0) 
133                         {
134                             getSigHandle()->deactivate(PEGASUS_SIGUSR1);
135                             getSigHandle()->deactivate(SIGTERM);
136                             return(-1);
137                         }
138                         else if (pid != 0)
139                         {
140                             //
141 h.sterling  1.1             // parent wait for child
142                             // if there is a problem with signal, parent process terminates
143                             // when waitTime expires
144                             //
145                             Uint32 waitTime = MAX_WAIT_TIME;
146                       
147                             while(!handleSigUsr1 && waitTime > 0)
148                             {
149                               sleep(1);
150                               waitTime--;
151                             }
152 w.otsuka    1.4             if( !handleSigUsr1 )
153                               {
154 dave.sudlik 1.11.18.3         //NOCHKSRC
155 w.otsuka    1.4               MessageLoaderParms parms("src.Service.ServerProcessUnix.CIMSERVER_START_TIMEOUT",
156                                 "The cimserver command timed out waiting for the CIM server to start.");
157                               PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) << PEGASUS_STD(endl);
158 dave.sudlik 1.11.18.3         //DOCHKSRC
159 w.otsuka    1.4             }
160 h.sterling  1.1             exit(graveError);
161                         }
162                         
163                         setsid();
164 marek       1.10        umask(S_IRWXG | S_IRWXO );
165                       
166                         // spawned daemon process doesn't need the old signal handlers of its parent
167                         getSigHandle()->deactivate(PEGASUS_SIGUSR1);
168                         getSigHandle()->deactivate(SIGTERM);
169 h.sterling  1.1       
170                         // get the pid of the cimserver process
171                         server_pid = getpid();
172                         return(0);
173                       }
174                       
175                       long ServerProcess::get_server_pid()
176                       {
177                           return server_pid;
178                       }
179                       
180 h.sterling  1.3       void ServerProcess::set_parent_pid(int pid)
181                       {
182                           parentPid = pid;
183                       }
184                       
185                       
186 jim.wunderlich 1.5       #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
187 h.sterling     1.1       
188                          //===========================================================================
189                          //  NAME          : verify_process_name
190                          //  DESCRIPTION   : Opens the 'stat' file in the /proc/<pid> directory to 
191                          //                  verify that the process name is that of the cimserver.
192                          //===========================================================================
193                          int verify_process_name(char *directory, const char* server_process_name) 
194                          {
195                              static char filename[80];
196                              static char buffer[512];
197                              int fd, bytesRead;
198                          
199                              // generate the name of the stat file in the process's /proc directory,
200                              // and open it
201                              sprintf(filename, "%s/%s", directory, "stat");
202                              if ( (fd = open(filename, O_RDONLY, 0)) == -1 ) 
203                              {
204                                  return -1;
205                              }
206                          
207                              // read the contents
208 h.sterling     1.1           if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 ) 
209                              {
210                                  close(fd);
211                                  return -1;
212                              }
213                          
214                              // null terminate the file contents
215                              buffer[bytesRead] = 0;
216                          
217                              close(fd);
218                          
219                              // the process name is the second element of the file contents and
220                              // is surrounded by parentheses. 
221                              //
222                              // find the positions of the parentheses in the file contents
223                              char * open_paren;
224                              char * close_paren;
225                              
226                              open_paren = strchr (buffer, '(');
227                              close_paren = strchr (buffer, ')');
228                              if (open_paren == NULL || close_paren == NULL || close_paren < open_paren)
229 h.sterling     1.1           {
230                                  return -1;
231                              }
232                          
233                              // allocate memory for the result
234 kumpf          1.6           AutoArrayPtr<char> process_name(new char[close_paren - open_paren]);
235 h.sterling     1.1       
236                              // copy the process name into the result  
237 kumpf          1.6           strncpy (process_name.get(), open_paren + 1, close_paren - open_paren -1);
238 h.sterling     1.1       
239                              // strncpy doesn't NULL-terminate the result, so do it here
240 kumpf          1.6           process_name.get()[close_paren - open_paren -1] = '\0';
241 h.sterling     1.1       
242 kumpf          1.6           if (strcmp(process_name.get(), server_process_name) != 0)
243 h.sterling     1.1           {
244                                  return -1;
245                              }
246                          
247                              return 0;
248                          }
249                          
250                          //=============================================================================
251                          // NAME           : get_proc
252                          // DESCRIPTION    : get_proc() makes a stat() system call on the directory in
253                          //                  /proc with a name that matches the pid of the cimserver.
254                          //                  It returns 0 if it successfully located the process dir
255                          //                  and verified that the process name matches that of the
256                          //                  cimserver.  It returns -1 if it fails to open /proc, or
257                          //                  the cimserver process does not exist.
258                          //=============================================================================
259                          int ServerProcess::get_proc(int pid)
260                          {
261                            static char path[32];
262                            static struct stat stat_buff;
263                          
264 h.sterling     1.1         sprintf(path, "/proc/%d", pid);
265                            if (stat(path, &stat_buff) == -1)          // process stopped running
266                            {
267                              return -1;
268                            }
269                          
270                           // get the process name to make sure it is the cimserver process
271                          // ATTN: skip verify for Solaris
272 jim.wunderlich 1.5       #if !defined(PEGASUS_OS_SOLARIS)
273 h.sterling     1.1         if ((verify_process_name(path, getProcessName())) == -1)
274                            {
275                              return -1;
276                            }
277                          #endif
278                          
279                            //
280                            // Check to see if this command process has the same pid as the cimserver
281                            // daemon process pid stored in the cimserver_start.conf file.  Since the
282                            // command has the same name as the cimserver daemon process, this could
283                            // happen after a system reboot.  If the pids are the same, cimserver 
284                            // isn't really running.
285                            //
286                            Uint32 mypid = System::getPID();
287                            if ((mypid == (unsigned)pid) || ((unsigned)parentPid == (unsigned)pid))
288                            {
289                                return -1;
290                            }
291                            return 0;
292                          }
293                          #endif
294 h.sterling     1.1       
295                          #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
296                          Boolean isProcRunning(pid_t pid)
297                          {
298                              W_PSPROC buf;                                                              
299                              int token = 0;
300                              memset(&buf, 0x00, sizeof(buf));                                           
301                              buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);        
302                              buf.ps_pathptr   =(char *) malloc(buf.ps_pathlen   =PS_PATHBLEN);          
303                              buf.ps_cmdptr    =(char *) malloc(buf.ps_cmdlen    =PS_CMDBLEN);
304                          
305 marek          1.11.18.2     while((token = w_getpsent(token, &buf, sizeof(buf))) > 0)
306                              {                   
307                                  if (buf.ps_pid==pid)
308                                  {
309                                      // If the process id is associated with the program
310                                      // "cimserver", then a cimserver is still running.
311                                      if (strstr(buf.ps_pathptr,"cimserver")!= NULL )
312                                      {
313 dave.sudlik    1.11.18.3             free(buf.ps_conttyptr);
314                                      free(buf.ps_pathptr);
315 h.sterling     1.1                   free(buf.ps_cmdptr);
316                                      return true;
317                                  }
318 marek          1.11.18.2             // pid found was not associated with a cimserver
319                                      break;
320                                  }
321                              } 
322 h.sterling     1.1       
323                              free(buf.ps_conttyptr);                                                    
324                              free(buf.ps_pathptr);                                                      
325                              free(buf.ps_cmdptr);
326                              return false;
327                          }
328                          #endif
329                          
330                          #if defined(PEGASUS_OS_AIX)
331                          
332                          /////////////////////////////////////////////////////////////////////////////
333                          // NAME           : processdata
334                          // FUNCTION       : it calls subroutine getprocs() to get information
335                          //                  about all processes.
336                          /////////////////////////////////////////////////////////////////////////////
337                          // ARGUMENTS:
338                          //              cnt: the number of the processes in the returned table
339                          // RETURN VALUES:
340                          //              when it successfully gets the process table entries,
341                          //              an array of procsinfo structures filled with process table
342                          //              entries are returned. Otherewise, a null pointer is
343 h.sterling     1.1       //              returned.
344                          //  
345                          /////////////////////////////////////////////////////////////////////////////
346                          struct procsinfo *processdata(int *cnt)
347                          {
348                                  struct procsinfo *proctable=NULL, *rtnp=NULL;
349                                  int count=1048576, rtncnt, repeat=1, nextp=0;
350                          
351                                  *cnt=0;
352                                  while ( repeat && (rtncnt=getprocs(rtnp,PROCSIZE,0,0,&nextp, count))>0)
353                                  {
354                                          if (!rtnp)
355                                          {
356                                                  count=rtncnt;
357                                                  proctable=(struct procsinfo *) malloc((size_t) \
358                                                                  PROCSIZE*count);
359                                                  if (!proctable)
360                                                          return NULL;
361                                                  rtnp=proctable;
362                                                  nextp=0;
363                                          } else
364 h.sterling     1.1                       {
365                                                  *cnt+=rtncnt;
366                                                  if (rtncnt>=count)
367                                                  {
368                                                          proctable=(struct procsinfo *) realloc(\
369                                                                  (void*)proctable, (size_t)\
370                                                                  (PROCSIZE*(*cnt+count)));
371                                                          if (!proctable)
372                                                                  return NULL;
373                                                          rtnp=proctable+(*cnt);
374                                                  } else
375                                                          repeat=0;
376                                          } // end of if(!rtnp)
377                                  } //end of while
378                                  return proctable;
379                          }
380                          
381                          /////////////////////////////////////////////////////////////////////////////
382                          // NAME           : aixcimsrvrunning
383                          // FUNCTION       : it figures out if the cimserver process is running
384                          //                  by checking the process table entries in the array
385 h.sterling     1.1       //                  returned from processdata(). If the cimserver process is
386                          //                  running and its pid is the same as the pid in the file
387                          //                  getPIDFileName(), it will return 0, otherwise it will
388                          //                  return -1.
389                          /////////////////////////////////////////////////////////////////////////////
390                          // ARGUMENTS:
391                          //              pid: the process identifier saved in the file
392                          //                   getPIDFileName()
393                          // RETURN VALUES:
394                          //              0: successful
395                          //              -1: errors
396                          //  
397                          /////////////////////////////////////////////////////////////////////////////
398                                 
399 h.sterling     1.2       int aixcimsrvrunning(pid_t pid, const char* processName)
400 h.sterling     1.1       {
401                                  int i,count;
402                                  struct procsinfo *proctable;
403                          
404                                  proctable=processdata(&count);
405                                  if (proctable==NULL)
406                                          return -1;
407                                  for (i=0;i<count;i++)
408 h.sterling     1.2                       if (!strcmp(proctable[i].pi_comm, processName) && \
409 h.sterling     1.1                           proctable[i].pi_pid==pid)
410                                          {
411                                                  free(proctable);
412                                                  return 0;
413                                          }
414                          
415                                  free(proctable);
416                                  return -1;
417                          }
418                          #endif
419                          
420                          Boolean ServerProcess::isCIMServerRunning(void)
421                          {
422                            FILE *pid_file;
423                            pid_t pid = 0;
424                          
425                            // open the file containing the CIMServer process ID
426                            pid_file = fopen(getPIDFileName(), "r");
427                            if (!pid_file)
428                            {
429                                return false;
430 h.sterling     1.1         }
431                          
432                            // get the pid from the file
433                            fscanf(pid_file, "%d\n", &pid);
434                          
435                            fclose(pid_file);
436                          
437                            if (pid == 0)
438                            {
439                               return false;
440                            }
441                          
442                            //
443                            // check to see if cimserver process is alive
444                            //
445                          #if defined(PEGASUS_OS_HPUX)
446                            struct pst_status pstru;
447                          
448                            int ret_code;
449                            ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
450                          
451 mateus.baur    1.11.18.1   if (ret_code != -1)
452 h.sterling     1.1         {
453                                //
454 mateus.baur    1.11.18.1       // Gets the command basename disregarding the command parameters
455 h.sterling     1.1             //
456 mateus.baur    1.11.18.1       char *execName = strchr(pstru.pst_cmd,' ');
457                                if (execName)
458                                {
459                                    *execName = '\0';
460                                }
461                                execName = basename(pstru.pst_cmd);
462                          
463                                if (strcmp(execName, getProcessName()) == 0)
464 h.sterling     1.1             {
465 mateus.baur    1.11.18.1           //
466                                    // Check to see if this command process has the same pid as the
467                                    // cimserver daemon process pid stored in the cimserver_start.conf
468                                    // file.  Since the command has the same name as the cimserver daemon
469                                    // process, this could happen after a system reboot.  If the pids are
470                                    // the same, cimserver isn't really running.
471                                    //
472                                    Uint32 mypid = System::getPID();
473                                    if ((mypid != pid) && (parentPid != pid))
474                                    {
475                                        // cimserver is running
476                                        return true;
477                                    }
478 h.sterling     1.1             }
479                            }
480                          #endif
481 jim.wunderlich 1.5       #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
482 h.sterling     1.1         if (get_proc(pid) != -1 )
483                            {
484                                // cimserver is running
485                                return true;
486                            }
487                          #endif
488                          #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
489                              return isProcRunning(pid);
490                          #endif
491                          #if defined(PEGASUS_OS_AIX)
492 h.sterling     1.2           if (aixcimsrvrunning(pid, getProcessName())!=-1)
493 h.sterling     1.1               return true;
494                          #endif
495                            return false;
496                          }
497                          
498                          int ServerProcess::cimserver_kill(int id) 
499                          { 
500                            FILE *pid_file;
501                            pid_t pid = 0;
502                            
503                            // open the file containing the CIMServer process ID
504                            pid_file = fopen(getPIDFileName(), "r");
505                            if (!pid_file) 
506                            {
507                                return (-1);
508                            }
509                          
510                            // get the pid from the file
511                            fscanf(pid_file, "%d\n", &pid);
512                          
513                            fclose(pid_file);
514 h.sterling     1.1       
515                            if (pid == 0)
516                            {
517                               System::removeFile(getPIDFileName());
518                               return (-1);
519                            }
520                          
521                            //
522                            // kill the process if it is still alive
523                            //
524                          #if defined(PEGASUS_OS_HPUX)
525                            struct pst_status pstru;
526                          
527                            int ret_code;
528                            ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
529                          
530                            if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
531                            {
532                                // cimserver is running, kill the process
533                                kill(pid, SIGKILL);
534                            }
535 h.sterling     1.1       #endif
536 jim.wunderlich 1.5       #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
537 h.sterling     1.1         if (get_proc(pid) != -1 )
538                            {
539                                kill(pid, SIGKILL);
540                            }
541                          #endif
542                          #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
543                            if (isProcRunning(pid)) {
544                                kill(pid, SIGKILL);
545                            }
546                          #endif
547                          #if defined(PEGASUS_OS_AIX)
548 h.sterling     1.2         if (!aixcimsrvrunning(pid, getProcessName()))
549 h.sterling     1.1               kill(pid,SIGKILL);
550                          #endif
551                            // remove the file
552                            System::removeFile(getPIDFileName());
553                            
554                            return(0);
555                          }
556                          
557                          // notify parent process to terminate so user knows that cimserver
558                          // is ready to serve CIM requests.
559                          void ServerProcess::notify_parent(int id)
560                          {
561                            pid_t ppid = getppid();
562                            if (id)
563                             kill(ppid, SIGTERM);
564                            else
565                             kill(ppid, PEGASUS_SIGUSR1); 
566                          }
567                          
568                          
569                          // Platform specific run
570 kumpf          1.7       int ServerProcess::platform_run(
571                              int argc,
572                              char** argv,
573                              Boolean shutdownOption,
574                              Boolean debugOutputOption)
575 h.sterling     1.1       {
576 kumpf          1.7           return cimserver_run(argc, argv, shutdownOption, debugOutputOption);
577 h.sterling     1.1       }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2