(file) Return to ServerProcessUnix.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Service

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2