(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 h.sterling 1.1 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
148                
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 h.sterling 1.1     // read the contents
169                    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 h.sterling 1.1     if (open_paren == NULL || close_paren == NULL || close_paren < open_paren)
190                    {
191                        return -1;
192                    }
193                
194                    // allocate memory for the result
195                    char * process_name;
196                    process_name = (char*) malloc(close_paren - open_paren - 1);
197                
198                    // copy the process name into the result  
199                    strncpy (process_name, open_paren + 1, close_paren - open_paren -1);
200                
201                    // strncpy doesn't NULL-terminate the result, so do it here
202                    process_name[close_paren - open_paren -1] = '\0';
203                
204                    if (strcmp(process_name, server_process_name) != 0)
205                    {
206                        return -1;
207                    }
208                
209                    return 0;
210 h.sterling 1.1 }
211                
212                //=============================================================================
213                // NAME           : get_proc
214                // DESCRIPTION    : get_proc() makes a stat() system call on the directory in
215                //                  /proc with a name that matches the pid of the cimserver.
216                //                  It returns 0 if it successfully located the process dir
217                //                  and verified that the process name matches that of the
218                //                  cimserver.  It returns -1 if it fails to open /proc, or
219                //                  the cimserver process does not exist.
220                //=============================================================================
221                int ServerProcess::get_proc(int pid)
222                {
223                  static char path[32];
224                  static struct stat stat_buff;
225                
226                  sprintf(path, "/proc/%d", pid);
227                  if (stat(path, &stat_buff) == -1)          // process stopped running
228                  {
229                    return -1;
230                  }
231 h.sterling 1.1 
232                 // get the process name to make sure it is the cimserver process
233                // ATTN: skip verify for Solaris
234                #if !defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
235                  if ((verify_process_name(path, getProcessName())) == -1)
236                  {
237                    return -1;
238                  }
239                #endif
240                
241                  //
242                  // Check to see if this command process has the same pid as the cimserver
243                  // daemon process pid stored in the cimserver_start.conf file.  Since the
244                  // command has the same name as the cimserver daemon process, this could
245                  // happen after a system reboot.  If the pids are the same, cimserver 
246                  // isn't really running.
247                  //
248                  Uint32 mypid = System::getPID();
249                  if ((mypid == (unsigned)pid) || ((unsigned)parentPid == (unsigned)pid))
250                  {
251                      return -1;
252 h.sterling 1.1   }
253                  return 0;
254                }
255                #endif
256                
257                #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
258                Boolean isProcRunning(pid_t pid)
259                {
260                    W_PSPROC buf;                                                              
261                    int token = 0;
262                    memset(&buf, 0x00, sizeof(buf));                                           
263                    buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);        
264                    buf.ps_pathptr   =(char *) malloc(buf.ps_pathlen   =PS_PATHBLEN);          
265                    buf.ps_cmdptr    =(char *) malloc(buf.ps_cmdlen    =PS_CMDBLEN);
266                
267                    token = w_getpsent(token, &buf, sizeof(buf));                              
268                    do {                                                                       
269                        token = w_getpsent(token, &buf, sizeof(buf));                          
270                        if (buf.ps_pid==pid) {
271                            free(buf.ps_conttyptr);                                                    
272                            free(buf.ps_pathptr);                                                      
273 h.sterling 1.1             free(buf.ps_cmdptr);
274                            return true;
275                        }
276                    } while(token>0);
277                
278                    free(buf.ps_conttyptr);                                                    
279                    free(buf.ps_pathptr);                                                      
280                    free(buf.ps_cmdptr);
281                    return false;
282                }
283                #endif
284                
285                #if defined(PEGASUS_OS_AIX)
286                
287                /////////////////////////////////////////////////////////////////////////////
288                // NAME           : processdata
289                // FUNCTION       : it calls subroutine getprocs() to get information
290                //                  about all processes.
291                /////////////////////////////////////////////////////////////////////////////
292                // ARGUMENTS:
293                //              cnt: the number of the processes in the returned table
294 h.sterling 1.1 // RETURN VALUES:
295                //              when it successfully gets the process table entries,
296                //              an array of procsinfo structures filled with process table
297                //              entries are returned. Otherewise, a null pointer is
298                //              returned.
299                //  
300                /////////////////////////////////////////////////////////////////////////////
301                struct procsinfo *processdata(int *cnt)
302                {
303                        struct procsinfo *proctable=NULL, *rtnp=NULL;
304                        int count=1048576, rtncnt, repeat=1, nextp=0;
305                
306                        *cnt=0;
307                        while ( repeat && (rtncnt=getprocs(rtnp,PROCSIZE,0,0,&nextp, count))>0)
308                        {
309                                if (!rtnp)
310                                {
311                                        count=rtncnt;
312                                        proctable=(struct procsinfo *) malloc((size_t) \
313                                                        PROCSIZE*count);
314                                        if (!proctable)
315 h.sterling 1.1                                 return NULL;
316                                        rtnp=proctable;
317                                        nextp=0;
318                                } else
319                                {
320                                        *cnt+=rtncnt;
321                                        if (rtncnt>=count)
322                                        {
323                                                proctable=(struct procsinfo *) realloc(\
324                                                        (void*)proctable, (size_t)\
325                                                        (PROCSIZE*(*cnt+count)));
326                                                if (!proctable)
327                                                        return NULL;
328                                                rtnp=proctable+(*cnt);
329                                        } else
330                                                repeat=0;
331                                } // end of if(!rtnp)
332                        } //end of while
333                        return proctable;
334                }
335                
336 h.sterling 1.1 /////////////////////////////////////////////////////////////////////////////
337                // NAME           : aixcimsrvrunning
338                // FUNCTION       : it figures out if the cimserver process is running
339                //                  by checking the process table entries in the array
340                //                  returned from processdata(). If the cimserver process is
341                //                  running and its pid is the same as the pid in the file
342                //                  getPIDFileName(), it will return 0, otherwise it will
343                //                  return -1.
344                /////////////////////////////////////////////////////////////////////////////
345                // ARGUMENTS:
346                //              pid: the process identifier saved in the file
347                //                   getPIDFileName()
348                // RETURN VALUES:
349                //              0: successful
350                //              -1: errors
351                //  
352                /////////////////////////////////////////////////////////////////////////////
353                       
354 h.sterling 1.2 int aixcimsrvrunning(pid_t pid, const char* processName)
355 h.sterling 1.1 {
356                        int i,count;
357                        struct procsinfo *proctable;
358                
359                        proctable=processdata(&count);
360                        if (proctable==NULL)
361                                return -1;
362                        for (i=0;i<count;i++)
363 h.sterling 1.2                 if (!strcmp(proctable[i].pi_comm, processName) && \
364 h.sterling 1.1                     proctable[i].pi_pid==pid)
365                                {
366                                        free(proctable);
367                                        return 0;
368                                }
369                
370                        free(proctable);
371                        return -1;
372                }
373                #endif
374                
375                Boolean ServerProcess::isCIMServerRunning(void)
376                {
377                  FILE *pid_file;
378                  pid_t pid = 0;
379                
380                  // open the file containing the CIMServer process ID
381                  pid_file = fopen(getPIDFileName(), "r");
382                  if (!pid_file)
383                  {
384                      return false;
385 h.sterling 1.1   }
386                
387                  // get the pid from the file
388                  fscanf(pid_file, "%d\n", &pid);
389                
390                  fclose(pid_file);
391                
392                  if (pid == 0)
393                  {
394                     return false;
395                  }
396                
397                  //
398                  // check to see if cimserver process is alive
399                  //
400                #if defined(PEGASUS_OS_HPUX)
401                  struct pst_status pstru;
402                
403                  int ret_code;
404                  ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
405                
406 h.sterling 1.1   if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
407                  {
408                      //
409                      // Check to see if this command process has the same pid as the 
410                      // cimserver daemon process pid stored in the cimserver_start.conf 
411                      // file.  Since the command has the same name as the cimserver daemon
412                      // process, this could happen after a system reboot.  If the pids are
413                      // the same, cimserver isn't really running.
414                      //
415                      Uint32 mypid = System::getPID();
416                      if ((mypid != pid) && (parentPid != pid))
417                      {
418                          // cimserver is running
419                          return true;
420                      }
421                  }
422                #endif
423                #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
424                  if (get_proc(pid) != -1 )
425                  {
426                      // cimserver is running
427 h.sterling 1.1       return true;
428                  }
429                #endif
430                #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
431                    return isProcRunning(pid);
432                #endif
433                #if defined(PEGASUS_OS_AIX)
434 h.sterling 1.2     if (aixcimsrvrunning(pid, getProcessName())!=-1)
435 h.sterling 1.1         return true;
436                #endif
437                  return false;
438                }
439                
440                int ServerProcess::cimserver_kill(int id) 
441                { 
442                  FILE *pid_file;
443                  pid_t pid = 0;
444                  
445                  // open the file containing the CIMServer process ID
446                  pid_file = fopen(getPIDFileName(), "r");
447                  if (!pid_file) 
448                  {
449                      return (-1);
450                  }
451                
452                  // get the pid from the file
453                  fscanf(pid_file, "%d\n", &pid);
454                
455                  fclose(pid_file);
456 h.sterling 1.1 
457                  if (pid == 0)
458                  {
459                     System::removeFile(getPIDFileName());
460                     return (-1);
461                  }
462                
463                  //
464                  // kill the process if it is still 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                  if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
473                  {
474                      // cimserver is running, kill the process
475                      kill(pid, SIGKILL);
476                  }
477 h.sterling 1.1 #endif
478                #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
479                  if (get_proc(pid) != -1 )
480                  {
481                      kill(pid, SIGKILL);
482                  }
483                #endif
484                #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
485                  if (isProcRunning(pid)) {
486                      kill(pid, SIGKILL);
487                  }
488                #endif
489                #if defined(PEGASUS_OS_AIX)
490 h.sterling 1.2   if (!aixcimsrvrunning(pid, getProcessName()))
491 h.sterling 1.1         kill(pid,SIGKILL);
492                #endif
493                  // remove the file
494                  System::removeFile(getPIDFileName());
495                  
496                  return(0);
497                }
498                
499                // notify parent process to terminate so user knows that cimserver
500                // is ready to serve CIM requests.
501                void ServerProcess::notify_parent(int id)
502                {
503                  pid_t ppid = getppid();
504                  if (id)
505                   kill(ppid, SIGTERM);
506                  else
507                   kill(ppid, PEGASUS_SIGUSR1); 
508                }
509                
510                
511                // Platform specific run
512 h.sterling 1.1 int ServerProcess::platform_run( int argc, char** argv, Boolean shutdownOption )
513                {
514                    return cimserver_run( argc, argv, shutdownOption );
515                }
516                
517                
518                
519                
520                
521                

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2