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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2