This is the mail archive of the frysk@sources.redhat.com mailing list for the frysk project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

half exited task testing


This is a C program that helps demonstrate a test to check when a task gets into a known exited but not-joined state and then tries to do an attach.

#define _GNU_SOURCE

#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <limits.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#include "util.h"

#define OKERRNO(FUNC) 	   \
  if (errno != 0) {	   \
    perror (#FUNC);	   \
    return 0;		   \
  }			   



static void
usage ()
{
  printf ("\
Usage:\n\
    [ --search ] <pid> <signal> <seconds> <nr-threads>\n\
Where:\n\
    --search	     Create a thread to search the states of the remaining threads\n\
    <pid> <signal>   Manager process to signal, and signal to use, once\n\
                     an operation has completed (e.g., running, thread\n\
                     created, thread exited).\n\
    <seconds>        Number of seconds that the program should run.\n\
    <nr-threads>     Number of threads that should be created\n\
");
  exit (1);
}



pthread_attr_t pthread_attr;

volatile static pid_t stid;
volatile static int halt;

volatile static long long count;
static void
update_counter ()
{
  static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
  OK (pthread_mutex_lock, (&count_mutex));
  count++;
  OK (pthread_mutex_unlock, (&count_mutex));
}

typedef void *(op_t)(void *);

void *
scan_thread (void *np)
{
  int fd = 0;
  char buf [1024];
  char buffer [1024];
  char state;

  while (1)    
    {
      errno = 0;

      if (halt) {
	trace ("halt");
	break;
      }

      sprintf ((char*)&buf, "/proc/%d/task/%d/stat", (int) getpid(), stid);
      fd = open (buf, O_RDONLY);
      if (errno != 0)
	continue;

      if (errno != 0) {
	perror ("reading");
	close (fd);
	return 0;
      }
      read (fd, buffer, sizeof (buffer));
      char* commEnd = strrchr (buffer, ')');
      state = buffer[(long)(commEnd - buffer + (void*)2)];
      trace ("tid=%d state=%c", stid, state);

      if (state == 'Z')
	return 0;
    }

  close (fd);
  return 0;
}

void *
op_clone (void *np)
{
  pthread_t tmp;
  pthread_t *thread = (pthread_t*)np;
  if (*thread != 0)
    OK (pthread_join, (*thread, np));
  *thread = pthread_self ();
  update_counter ();
  stid = gettid ();
  if (halt)
    return NULL;
  OK (pthread_create, (&tmp, &pthread_attr, op_clone, np));
  return NULL;
}

int
main (int argc, char *argv[])
{
  int i;
  int n;
  int sig;
  int pid;
  int sec;
  int create_search_thread = 0;
  pthread_t *threads = 0;
  pthread_t p;

  int argi = 1;
  op_t *op = op_clone;
  while (argi < argc) {
    if (strcmp (argv[argi], "--search") == 0)
      create_search_thread = 1;
    else
      break;
    argi++;
  }

  if (argi + 4 > argc)
    usage ();

  pid = atol (argv[argi++]);
  sig = atol (argv[argi++]);
  sec = atol (argv[argi++]);
  n = atol (argv[argi++]) + 1;

  OK (pthread_attr_init, (&pthread_attr));
  OK (pthread_attr_setstacksize, (&pthread_attr, PTHREAD_STACK_MIN));

  threads = calloc (n, sizeof (pthread_t));
  for (i = 1; i < n; i++) {
    OK (pthread_create, (&p, &pthread_attr, op_clone, &threads[i]));
    trace ("id=%x", (unsigned int)p);
  }
  if (create_search_thread)
    OK (pthread_create, (&p, &pthread_attr, scan_thread, &threads[0]));

  kill (pid, sig); // ack.
  sleep (sec);
  trace ("sec=%d halt=%d \n", sec, halt);
  halt = 1;
  
  trace ("sec=%d halt=%d \n", sec, halt);
  //  for (i = 0; i < n; i++) {
  //    void *result;
  //    pthread_join (threads[i], &result);
  //  }

  printf ("count %lld\n", count);
  exit (0);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]