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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2