Пример #1
0
BOOL StopGCThread ( void *Ptr ) {
  int err;

  Slot_Mgr_Shr_t               *MemPtr              = (Slot_Mgr_Shr_t *) Ptr;
  void *Status;

  if ( ! ThreadRunning ) {
    DbgLog(DL0,"StopGCThread was called when the garbage collection thread was not running");
    return FALSE;
  }

  DbgLog(DL0, "StopGCThread: tid %d is stopping the garbage collection thread (tid %d)", pthread_self(), GCThread);

  /* Cause the GC thread to be cancelled */
  if ( ( err = pthread_cancel(GCThread)) != 0 ) {
    DbgLog(DL0,"StopGCThread: pthread_cancel returned %s (%d; %#x)", SysConst(err), err, err );
    return FALSE;
  }

  /* Synchronize with the GC thread (aka: wait for it to terminate) */
  if ( (err = pthread_join ( GCThread, &Status ) ) != 0 ) {
    DbgLog(DL0,"StopGCThread: pthread_join returned %s (%d; %#x)", SysConst(err), err, err );
    return FALSE;
  }

  if ( Status != PTHREAD_CANCELED ) {
    DbgLog(DL0,"Hmm.  Thread was cancelled, but didn't return the appropriate return status");
  }

  ThreadRunning = FALSE;
  return TRUE;

}
Пример #2
0
BOOL StartGCThread ( Slot_Mgr_Shr_t *MemPtr ) {

  int err;

#if !(THREADED)
  return TRUE;
#endif

  if ( ThreadRunning ) {
    DbgLog (DL0, "StartGCThread: Thread already running.");
    return FALSE;
  }

  if ( ( err = pthread_create( &GCThread, NULL, GCMain, ((void *)MemPtr) ) ) != 0 ) {
    DbgLog(DL0,"StartGCThread: pthread_create returned %s (%d; %#x)", SysConst(err), err, err );
    return FALSE;
  }

  ThreadRunning = TRUE;

#ifdef DEV
  // Only development builds
  LogLog ( "StartGCThread: garbage collection thread started as ID %d (%#x) by ID %d (%#x)", GCThread, GCThread, pthread_self(), pthread_self() );
#endif
  return TRUE;

}
Пример #3
0
BOOL SaveStartupDirectory ( char *Arg0 ) {

  unsigned int        Err;
  char                cwd[PATH_MAX+1];
  char                arg[PATH_MAX+1];
  char                *dname = NULL;


  ASSERT( Arg0 != NULL );

  if ( getcwd ( cwd, PathSize ) == NULL ) {
    Err = errno;
    DbgLog(DL0,"SaveStartupDirectory: getcwd returned %s (%d)", SysConst(Err), Err);
    return FALSE;
  }

  /* Free previous copy */
  if ( StartDir != NULL ) {
    free(StartDir);
    StartDir = NULL;
  }

  /* Allocate memory */
  if ( (StartDir = calloc ( PathSize, sizeof(char) ) ) == NULL ) {
    Err = errno;
    DbgLog(DL0,"SaveStartupDirectory: Unable to allocate %d bytes of memory for storage of the CWD. %s (%d)\n", SysConst(Err), Err );
    exit(1);
  }


  /* If Arg0 contains a /, then dirname(Arg0) is appended to cwd */
      /* This will handle the case where you were in directory foo, and started the daemon
       * as bar/daemon
       */

  /* FIXME: This will not work properly if the daemon was found by searching the PATH */

  /* Make a local copy of the string because dirname() modifies it's arguments */
  strcpy( arg, Arg0 );

  dname = dirname ( arg );          /* note that dirname("daemon") and dirname("./daemon") will return "." */
  if ( strcmp( dname, "." ) != 0 ) {
    /* there's a / in it... */
    sprintf(StartDir, "%s/%s", cwd, dname);
  } else {
    sprintf(StartDir, "%s", cwd);
  }

  return TRUE;

}
Пример #4
0
BOOL IsValidProcessEntry ( pid_t_64 pid, time_t_64 RegTime ) {

  int                    Err;
  int valid;
  proc_t *p;
  proc_t procstore;

  /* If kill(pid, 0) returns -1 and errno/Err = ESRCH, the pid doesn't exist */
  if ( kill(pid, 0) == -1 ) {
    Err = errno;
    if ( Err == ESRCH ) {
      /* The process was not found */
      DbgLog(DL3, "IsValidProcessEntry: PID %d was not found in the process table (kill() returned %s)", pid, SysConst(Err) );
      return FALSE;
    } else {
      /* some other error occurred */
      DbgLog(DL3, "IsValidProcessEntry: kill() returned %s (%d; %#x)", SysConst(Err), Err, Err);
      return FALSE;
    }
  } /* end if kill */

  /* Okay, the process exists, now we see if it's really ours */

#ifdef ALLOCATE
  p = (proc_t *)malloc(sizeof(proc_t));
#else
  p = &procstore;
  memset(p, 0, sizeof(proc_t));
#endif

  if( !(valid = Stat2Proc( (int)pid, p )) )
    return FALSE;

  if ( p->pid == pid ) {
    if ( RegTime >= p->start_time ) {   // checking for matching start times
      return TRUE;
    } else {
      /* p->start_time contains the time at which the process began ??  (22nd element in /proc/<pid>/stat file) */
      DbgLog(DL1, "IsValidProcessEntry: PID %d started at %lu; registered at %ld", pid, p->start_time, RegTime);
      DbgLog(DL4, "IsValidProcessEntry: PID Returned %d flags at %#x; state at %#x", p->pid, p->flags, p->state);
    }
  }

  return FALSE;

}
Пример #5
0
BOOL IsValidProcessEntry ( pid_t pid, time_t RegTime ) {
#endif

#ifdef PKCS64
  pid_t                     Index     = (pid_t)pid;
#else
  pid_t                     Index     = pid;
#endif


  struct procsinfo64     ProcInfo[1]; /* getprocs wants arrays; I'm just being anal; I know it's stupid to declare an array of 1 element */
  struct fdsinfo_2000    FileInfo[1]; /* if you pass a struct fdsinfo, you get a core dump */
  int                    Count = 1;
  int                    Err;
  
  /* Note that Index is modified by this call; use pid to see what process id we're looking for afterwards */
  if ( getprocs ( &(ProcInfo[0]), sizeof(ProcInfo), NULL, NULL, &Index, Count ) != Count ) {
    Err = errno;
    if ( Err == EINVAL ) {
      /* The process was not found */
      DbgLog(DL3, "IsValidProcessEntry: PID %d was not found in the process table (getprocs() returned %s)", pid, SysConst(Err) );
      return FALSE;
    } else {
      /* some other error occurred */
      DbgLog(DL3,"IsValidProcessEntry: getprocs() returned %s (%d; %#x)", SysConst(Err), Err, Err);
      return FALSE;
    }
  } /* end if getprocs */

  /* Okay, the process exists, now we see if it's really ours */

  if ( ProcInfo[0].pi_pid == pid) {
     if ( RegTime >= ProcInfo[0].pi_start ) {
       return TRUE;
     } else {
       /* ProcInfo[0].pi_start contains the time at which the process began */
       DbgLog(DL1, "IsValidProcessEntry: PID %d started at %lld; registered at %ld", pid, ProcInfo[0].pi_start, RegTime);
       DbgLog(DL4, "IsValidProcessEntry: PID Returned %d flags at %#x; state at %#x index %d", ProcInfo[0].pi_pid, ProcInfo[0].pi_flags, ProcInfo[0].pi_state,Index);
     }

  }
  return FALSE;

}
Пример #6
0
BOOL CheckForGarbage ( Slot_Mgr_Shr_t *MemPtr ) {

  int               SlotIndex;
  int               ProcIndex;
  int               Err;
  BOOL              ValidPid;

  ASSERT( MemPtr != NULL_PTR );
  #ifdef DEV
    DbgLog(DL5, "Thread %d is checking for garbage", pthread_self());
  #endif /* DEV */


  #ifdef DEV
    DbgLog (DL5, "Garbage collection attempting global shared memory lock");
  #endif /* DEV */

  /* Grab the global Shared mem mutex since we might modify global_session_count */

#ifdef PKCS64
  Err = msem_lock(&(MemPtr->slt_mutex),0);
#else
  Err = pthread_mutex_lock ( &(MemPtr->slt_mutex) );
#endif

  if ( Err != 0 ) {
    DbgLog (DL0, "Garbage collection: Locking attempt for global shmem mutex returned %s", SysConst(Err) );
    return FALSE;
  }

  #ifdef DEV
  DbgLog ( DL5, "Garbage collection: Got global shared memory lock");
  #endif /* DEV */


  for ( ProcIndex = 0; ProcIndex < NUMBER_PROCESSES_ALLOWED; ProcIndex++ ) {

#ifdef PKCS64
    Slot_Mgr_Proc_t_64 *pProc = &(MemPtr->proc_table[ProcIndex]);
#else
    Slot_Mgr_Proc_t   *pProc = &(MemPtr->proc_table[ProcIndex]);
#endif

    ASSERT(pProc != NULL_PTR);

    if ( ! (pProc->inuse) ) {
      continue;
    }

    ValidPid = ( (IsValidProcessEntry ( pProc->proc_id, pProc->reg_time )) && (pProc->proc_id != 0) );


    if ( ( pProc->inuse ) && (! ValidPid ) ) {

      #ifdef DEV
        DbgLog(DL1, "Garbage collection routine found bad entry for pid %d (Index: %d); removing from table", pProc->proc_id, ProcIndex );
      #endif /* DEV */

      /*                         */
      /* Clean up session counts */
      /*                         */
      for ( SlotIndex = 0; SlotIndex < NUMBER_SLOTS_MANAGED; SlotIndex++ ) {


#ifdef PKCS64
	unsigned int *pGlobalSessions    = &(MemPtr->slot_info[SlotIndex].global_sessions);
	unsigned int *pProcSessions      = &(pProc->slot_session_count[SlotIndex]);
#else
	int *pGlobalSessions    = &(MemPtr->slot_info[SlotIndex].global_sessions);
	int *pProcSessions      = &(pProc->slot_session_count[SlotIndex]);
#endif


	if ( *pProcSessions > 0 ) {

  	  #ifdef DEV
	    DbgLog ( DL2, "GC: Invalid pid (%d) is holding %d sessions open on slot %d.  Global session count for this slot is %d", pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
          #endif /* DEV */

	  if ( *pProcSessions > *pGlobalSessions ) {
	    #ifdef DEV
	      WarnLog ( "Garbage Collection: Illegal values in table for defunct process");
	      DbgLog  ( DL0, "Garbage collection: A process ( Index: %d, pid: %d ) showed %d sessions open on slot %s, but the global count for this slot is only %d",
			ProcIndex, pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
	    #endif /* DEV */
	    *pGlobalSessions = 0;
	  } else {
	    *pGlobalSessions -= *pProcSessions;
	  }

	  *pProcSessions = 0;

	} /* end if *pProcSessions */

      } /* end for SlotIndex */


      /*                                      */
      /* NULL out everything except the mutex */
      /*                                      */

      #if PER_PROCESS_MUTEXES
        /* Grab the mutex for this proc's shared memory data structure */

#ifdef PKCS64
        Err = msem_lock(&(pProc->proc_mutex),MSEM_IF_NOWAIT);
#else 
        Err = pthread_mutex_trylock( &(pProc->proc_mutex) );
#endif

	if ( ( Err != 0 ) ) {
	  /* We didn't get the lock! */
	  /* Attempting to destroy a locked mutex results in undefined behavior */
	  /* http://techlib.austin.ibm.com/techlib/manuals/adoclib/libs/basetrf1/pthreads.htm */
	  DbgLog (DL0,"Unable to get per-process mutex for pid %d (%s) - skipping", pProc->proc_id, SysConst( Err ) );

	  /* 
	     The exit routine will figure out that this is an invalid process entry
	     (by calling IsValidProcessEntry()), and won't prevent the slotd from exiting
	     because of this entry.
	     */

	  continue;
	}
      #endif /* PER_PROCESS_MUTEXES */

      memset( &(pProc->inuse),              '\0', sizeof(pProc->inuse) );
      memset( &(pProc->proc_id),            '\0', sizeof(pProc->proc_id) );
      memset( &(pProc->slotmap),            '\0', sizeof(pProc->slotmap) );
      memset( &(pProc->blocking),           '\0', sizeof(pProc->blocking ));
      memset( &(pProc->error),              '\0', sizeof(pProc->error) );
      memset( &(pProc->slot_session_count), '\0', sizeof(pProc->slot_session_count) );
      memset( &(pProc->reg_time),           '\0', sizeof(pProc->reg_time) );

    } /* end if inuse && ValidPid */
    

    #if PER_PROCESS_MUTEXES

#ifdef PKCS64 
      msem_unlock(&(pProc->proc_mutex),0)
    
#else
      pthread_mutex_unlock( &(pProc->proc_mutex));
#endif

    #endif /* PER_PROCESS_MUTEXES  */
   
    
  } /* end for ProcIndex */
  
#ifdef PKCS64
  msem_unlock(&(MemPtr->slt_mutex),0);
#else
  pthread_mutex_unlock ( &(MemPtr->slt_mutex) );
#endif

  DbgLog ( DL5, "Garbage collection: Released global shared memory lock");

  return TRUE;
  
}
Пример #7
0
BOOL CheckForGarbage ( Slot_Mgr_Shr_t *MemPtr ) {

  int               SlotIndex;
  int               ProcIndex;
  int               Err;
  BOOL              ValidPid;

  ASSERT( MemPtr != NULL_PTR );
  #ifdef DEV
    DbgLog(DL5, "Thread %d is checking for garbage", pthread_self());
  #endif /* DEV */


  #ifdef DEV
    DbgLog (DL5, "Garbage collection attempting global shared memory lock");
  #endif /* DEV */

  /* Grab the global Shared mem mutex since we might modify global_session_count */

    Err = XProcLock();
  if ( Err != TRUE ) {
    DbgLog (DL0, "Garbage collection: Locking attempt for global shmem mutex returned %s", SysConst(Err) );
    return FALSE;
  }

  #ifdef DEV
  DbgLog ( DL5, "Garbage collection: Got global shared memory lock");
  #endif /* DEV */


  for ( ProcIndex = 0; ProcIndex < NUMBER_PROCESSES_ALLOWED; ProcIndex++ ) {

    Slot_Mgr_Proc_t_64 *pProc = &(MemPtr->proc_table[ProcIndex]);

    ASSERT(pProc != NULL_PTR);

    if ( ! (pProc->inuse) ) {
      continue;
    }

    ValidPid = ( (IsValidProcessEntry ( pProc->proc_id, pProc->reg_time )) && (pProc->proc_id != 0) );


    if ( ( pProc->inuse ) && (! ValidPid ) ) {

      #ifdef DEV
        DbgLog(DL1, "Garbage collection routine found bad entry for pid %d (Index: %d); removing from table", pProc->proc_id, ProcIndex );
      #endif /* DEV */

      /*                         */
      /* Clean up session counts */
      /*                         */
      for ( SlotIndex = 0; SlotIndex < NUMBER_SLOTS_MANAGED; SlotIndex++ ) {

	unsigned int *pGlobalSessions =
		      &(MemPtr->slot_global_sessions[SlotIndex]);
	unsigned int *pProcSessions = &(pProc->slot_session_count[SlotIndex]);

	if ( *pProcSessions > 0 ) {

  	  #ifdef DEV
	    DbgLog ( DL2, "GC: Invalid pid (%d) is holding %d sessions open on slot %d.  Global session count for this slot is %d", pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
          #endif /* DEV */

	  if ( *pProcSessions > *pGlobalSessions ) {
	    #ifdef DEV
	      WarnLog ( "Garbage Collection: Illegal values in table for defunct process");
	      DbgLog  ( DL0, "Garbage collection: A process ( Index: %d, pid: %d ) showed %d sessions open on slot %s, but the global count for this slot is only %d",
			ProcIndex, pProc->proc_id, *pProcSessions, SlotIndex, *pGlobalSessions );
	    #endif /* DEV */
	    *pGlobalSessions = 0;
	  } else {
	    *pGlobalSessions -= *pProcSessions;
	  }

	  *pProcSessions = 0;

	} /* end if *pProcSessions */

      } /* end for SlotIndex */


      /*                                      */
      /* NULL out everything except the mutex */
      /*                                      */

      memset( &(pProc->inuse),              '\0', sizeof(pProc->inuse) );
      memset( &(pProc->proc_id),            '\0', sizeof(pProc->proc_id) );
      memset( &(pProc->slotmap),            '\0', sizeof(pProc->slotmap) );
      memset( &(pProc->blocking),           '\0', sizeof(pProc->blocking ));
      memset( &(pProc->error),              '\0', sizeof(pProc->error) );
      memset( &(pProc->slot_session_count), '\0', sizeof(pProc->slot_session_count) );
      memset( &(pProc->reg_time),           '\0', sizeof(pProc->reg_time) );

    } /* end if inuse && ValidPid */

  } /* end for ProcIndex */

  XProcUnLock();
  DbgLog ( DL5, "Garbage collection: Released global shared memory lock");

  return TRUE;

}
Пример #8
0
  BOOL DestroyConditionVariables ( void ) {

    int err;

    if ( (err = pthread_mutex_destroy ( &(shmp->shmem_cv_mutex) ) ) != 0 ) {
      DbgLog(DL0,"DestroyConditionVariables: pthread_mutex_destroy returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }

    if ( (err = pthread_cond_destroy( &(shmp->shmem_cv) ) ) != 0 ) {
      DbgLog(DL0,"DestroyConditionVariables: pthread_cond_destroy returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }

    if ( (err = pthread_condattr_destroy( &(shmp->shmem_cv_attr) ) ) != 0 ) {
      DbgLog(DL0,"DestroyConditionVariables: pthread_condattr_destroy returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }

    return TRUE;

  }
Пример #9
0
  BOOL InitializeConditionVariables ( void ) {
  
    int err;

    if ( (err = pthread_condattr_init( &(shmp->shmem_cv_attr) ) ) != 0 ) {
      DbgLog(DL0,"InitializeConditionVariables: pthread_condattr_init returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }


    if ( (err = pthread_cond_init( &(shmp->shmem_cv), &(shmp->shmem_cv_attr) ) ) != 0 ) {
      DbgLog(DL0,"InitializeConditionVariables: pthread_cond_init returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }

    if ( (err = pthread_mutex_init( &(shmp->shmem_cv_mutex), &mtxattr ) ) != 0 ) {
      DbgLog(DL0,"InitializeConditionVariables: pthread_mutex_init returned %s (%d; %#x)\n", SysConst(err), err, err);
      return FALSE;
    }

    return TRUE;

  }