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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2