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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2