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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2