(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                       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 marek          1.11.18.2     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 marek          1.11.18.2             // 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.11.18.1   if (ret_code != -1)
447 h.sterling     1.1         {
448                                //
449 mateus.baur    1.11.18.1       // Gets the command basename disregarding the command parameters
450 h.sterling     1.1             //
451 mateus.baur    1.11.18.1       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.11.18.1           //
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