(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                              token = w_getpsent(token, &buf, sizeof(buf));                              
301                              do {                                                                       
302                                  token = w_getpsent(token, &buf, sizeof(buf));                          
303                                  if (buf.ps_pid==pid) {
304                                      free(buf.ps_conttyptr);                                                    
305                                      free(buf.ps_pathptr);                                                      
306                                      free(buf.ps_cmdptr);
307                                      return true;
308                                  }
309                              } while(token>0);
310 h.sterling     1.1       
311                              free(buf.ps_conttyptr);                                                    
312                              free(buf.ps_pathptr);                                                      
313                              free(buf.ps_cmdptr);
314                              return false;
315                          }
316                          #endif
317                          
318                          #if defined(PEGASUS_OS_AIX)
319                          
320                          /////////////////////////////////////////////////////////////////////////////
321                          // NAME           : processdata
322                          // FUNCTION       : it calls subroutine getprocs() to get information
323                          //                  about all processes.
324                          /////////////////////////////////////////////////////////////////////////////
325                          // ARGUMENTS:
326                          //              cnt: the number of the processes in the returned table
327                          // RETURN VALUES:
328                          //              when it successfully gets the process table entries,
329                          //              an array of procsinfo structures filled with process table
330                          //              entries are returned. Otherewise, a null pointer is
331 h.sterling     1.1       //              returned.
332                          //  
333                          /////////////////////////////////////////////////////////////////////////////
334                          struct procsinfo *processdata(int *cnt)
335                          {
336                                  struct procsinfo *proctable=NULL, *rtnp=NULL;
337                                  int count=1048576, rtncnt, repeat=1, nextp=0;
338                          
339                                  *cnt=0;
340                                  while ( repeat && (rtncnt=getprocs(rtnp,PROCSIZE,0,0,&nextp, count))>0)
341                                  {
342                                          if (!rtnp)
343                                          {
344                                                  count=rtncnt;
345                                                  proctable=(struct procsinfo *) malloc((size_t) \
346                                                                  PROCSIZE*count);
347                                                  if (!proctable)
348                                                          return NULL;
349                                                  rtnp=proctable;
350                                                  nextp=0;
351                                          } else
352 h.sterling     1.1                       {
353                                                  *cnt+=rtncnt;
354                                                  if (rtncnt>=count)
355                                                  {
356                                                          proctable=(struct procsinfo *) realloc(\
357                                                                  (void*)proctable, (size_t)\
358                                                                  (PROCSIZE*(*cnt+count)));
359                                                          if (!proctable)
360                                                                  return NULL;
361                                                          rtnp=proctable+(*cnt);
362                                                  } else
363                                                          repeat=0;
364                                          } // end of if(!rtnp)
365                                  } //end of while
366                                  return proctable;
367                          }
368                          
369                          /////////////////////////////////////////////////////////////////////////////
370                          // NAME           : aixcimsrvrunning
371                          // FUNCTION       : it figures out if the cimserver process is running
372                          //                  by checking the process table entries in the array
373 h.sterling     1.1       //                  returned from processdata(). If the cimserver process is
374                          //                  running and its pid is the same as the pid in the file
375                          //                  getPIDFileName(), it will return 0, otherwise it will
376                          //                  return -1.
377                          /////////////////////////////////////////////////////////////////////////////
378                          // ARGUMENTS:
379                          //              pid: the process identifier saved in the file
380                          //                   getPIDFileName()
381                          // RETURN VALUES:
382                          //              0: successful
383                          //              -1: errors
384                          //  
385                          /////////////////////////////////////////////////////////////////////////////
386                                 
387 h.sterling     1.2       int aixcimsrvrunning(pid_t pid, const char* processName)
388 h.sterling     1.1       {
389                                  int i,count;
390                                  struct procsinfo *proctable;
391                          
392                                  proctable=processdata(&count);
393                                  if (proctable==NULL)
394                                          return -1;
395                                  for (i=0;i<count;i++)
396 h.sterling     1.2                       if (!strcmp(proctable[i].pi_comm, processName) && \
397 h.sterling     1.1                           proctable[i].pi_pid==pid)
398                                          {
399                                                  free(proctable);
400                                                  return 0;
401                                          }
402                          
403                                  free(proctable);
404                                  return -1;
405                          }
406                          #endif
407                          
408                          Boolean ServerProcess::isCIMServerRunning(void)
409                          {
410                            FILE *pid_file;
411                            pid_t pid = 0;
412                          
413                            // open the file containing the CIMServer process ID
414                            pid_file = fopen(getPIDFileName(), "r");
415                            if (!pid_file)
416                            {
417                                return false;
418 h.sterling     1.1         }
419                          
420                            // get the pid from the file
421                            fscanf(pid_file, "%d\n", &pid);
422                          
423                            fclose(pid_file);
424                          
425                            if (pid == 0)
426                            {
427                               return false;
428                            }
429                          
430                            //
431                            // check to see if cimserver process is alive
432                            //
433                          #if defined(PEGASUS_OS_HPUX)
434                            struct pst_status pstru;
435                          
436                            int ret_code;
437                            ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
438                          
439 mateus.baur    1.11.18.1   if (ret_code != -1)
440 h.sterling     1.1         {
441                                //
442 mateus.baur    1.11.18.1       // Gets the command basename disregarding the command parameters
443 h.sterling     1.1             //
444 mateus.baur    1.11.18.1       char *execName = strchr(pstru.pst_cmd,' ');
445                                if (execName)
446                                {
447                                    *execName = '\0';
448                                }
449                                execName = basename(pstru.pst_cmd);
450                          
451                                if (strcmp(execName, getProcessName()) == 0)
452 h.sterling     1.1             {
453 mateus.baur    1.11.18.1           //
454                                    // Check to see if this command process has the same pid as the
455                                    // cimserver daemon process pid stored in the cimserver_start.conf
456                                    // file.  Since the command has the same name as the cimserver daemon
457                                    // process, this could happen after a system reboot.  If the pids are
458                                    // the same, cimserver isn't really running.
459                                    //
460                                    Uint32 mypid = System::getPID();
461                                    if ((mypid != pid) && (parentPid != pid))
462                                    {
463                                        // cimserver is running
464                                        return true;
465                                    }
466 h.sterling     1.1             }
467                            }
468                          #endif
469 jim.wunderlich 1.5       #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
470 h.sterling     1.1         if (get_proc(pid) != -1 )
471                            {
472                                // cimserver is running
473                                return true;
474                            }
475                          #endif
476                          #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
477                              return isProcRunning(pid);
478                          #endif
479                          #if defined(PEGASUS_OS_AIX)
480 h.sterling     1.2           if (aixcimsrvrunning(pid, getProcessName())!=-1)
481 h.sterling     1.1               return true;
482                          #endif
483                            return false;
484                          }
485                          
486                          int ServerProcess::cimserver_kill(int id) 
487                          { 
488                            FILE *pid_file;
489                            pid_t pid = 0;
490                            
491                            // open the file containing the CIMServer process ID
492                            pid_file = fopen(getPIDFileName(), "r");
493                            if (!pid_file) 
494                            {
495                                return (-1);
496                            }
497                          
498                            // get the pid from the file
499                            fscanf(pid_file, "%d\n", &pid);
500                          
501                            fclose(pid_file);
502 h.sterling     1.1       
503                            if (pid == 0)
504                            {
505                               System::removeFile(getPIDFileName());
506                               return (-1);
507                            }
508                          
509                            //
510                            // kill the process if it is still alive
511                            //
512                          #if defined(PEGASUS_OS_HPUX)
513                            struct pst_status pstru;
514                          
515                            int ret_code;
516                            ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
517                          
518                            if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
519                            {
520                                // cimserver is running, kill the process
521                                kill(pid, SIGKILL);
522                            }
523 h.sterling     1.1       #endif
524 jim.wunderlich 1.5       #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
525 h.sterling     1.1         if (get_proc(pid) != -1 )
526                            {
527                                kill(pid, SIGKILL);
528                            }
529                          #endif
530                          #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
531                            if (isProcRunning(pid)) {
532                                kill(pid, SIGKILL);
533                            }
534                          #endif
535                          #if defined(PEGASUS_OS_AIX)
536 h.sterling     1.2         if (!aixcimsrvrunning(pid, getProcessName()))
537 h.sterling     1.1               kill(pid,SIGKILL);
538                          #endif
539                            // remove the file
540                            System::removeFile(getPIDFileName());
541                            
542                            return(0);
543                          }
544                          
545                          // notify parent process to terminate so user knows that cimserver
546                          // is ready to serve CIM requests.
547                          void ServerProcess::notify_parent(int id)
548                          {
549                            pid_t ppid = getppid();
550                            if (id)
551                             kill(ppid, SIGTERM);
552                            else
553                             kill(ppid, PEGASUS_SIGUSR1); 
554                          }
555                          
556                          
557                          // Platform specific run
558 kumpf          1.7       int ServerProcess::platform_run(
559                              int argc,
560                              char** argv,
561                              Boolean shutdownOption,
562                              Boolean debugOutputOption)
563 h.sterling     1.1       {
564 kumpf          1.7           return cimserver_run(argc, argv, shutdownOption, debugOutputOption);
565 h.sterling     1.1       }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2