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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2