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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2