Real World Example
#include <pthreadutil.h> #include <sys/param.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <stdio.h> void *netfinger(); void usage(int eval) { fprintf(stderr, "usage: finger [-lps] [-c] [-t|T ] [-f ] [login ...]\n"); exit(eval); } /* * These globals are set initialy and then are only read. * They do not need mutexes. */ int thread_time = 0, program_timeout = 0, lflag = 0; pthread_tad_t parse_file_tad; pthread_tad_t netfinger_tad; void * timeout_thread(void * arg) { sleep(program_timeout); exit(0); } void * parse_file(void * arg) { char hostname[MAXHOSTNAMELEN]; char * filename = arg; pthread_atexit_t atexit_id; pthread_attr_t attr; pthread_t thread_id; char * thread_arg; FILE * fp; int len; netsetupwait(); /* Parse the file and create a thread per connection */ if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Can't open file %s\n", filename); pthread_exit(NULL); } pthread_cleanup_push(fclose, fp); if (pthread_attr_init(&attr)) { fprintf(stderr, "Error: Can't initialize thread attributes\n"); exit(2); } pthread_cleanup_push(pthread_attr_destroy, &attr); while (fgets(hostname, MAXHOSTNAMELEN, fp)) { if ((thread_arg = (char *)malloc(len = strlen(hostname))) == NULL) { fprintf(stderr, "Error: out of memory\n"); exit(2); } hostname[len - 1] = '\0'; strcpy(thread_arg, hostname); pthread_attr_setcleanup(&attr, free, thread_arg); if (pthread_tad_create(&netfinger_tad, &thread_id, NULL, netfinger, thread_arg)) { fprintf(stderr, "Error: pthread_tad_create() netfinger_tad.\n"); exit(2); } } pthread_cleanup_pop(1); pthread_cleanup_pop(1); pthread_exit(NULL); } main(int argc, char **argv) { pthread_atexit_t atexit_id; pthread_t thread_id; int max_count = 0; char ch; /* getopt variables */ extern char *optarg; extern int optind; /* Setup tad for parse_file() threads */ if (pthread_tad_init(&parse_file_tad, max_count)) { fprintf(stderr,"Error: couldn't create parse_file() TAD.\n"); exit(1); } while ((ch = getopt(argc, argv, "c:f:t:T:ls")) != (char)EOF) switch(ch) { case 't': /* Time to let each thread run */ if ((thread_time = atoi(optarg)) <= 0) { usage(1); } break; case 'T': /* Time to let entire program run */ if ((program_timeout = atoi(optarg)) <= 0) { usage(1); } break; case 'f': /* Parse file for list of places to finger */ if (pthread_tad_create(&parse_file_tad, &thread_id, NULL, parse_file, optarg)) { fprintf(stderr,"Error: pthread_tad_create() parse_file_tad.\n"); exit(1); } break; case 'c': max_count = atoi(optarg); break; case 'l': /* long format */ lflag = 1; break; case 's': /* short format */ lflag = 0; break; case '?': usage(0); default: usage(1); } /* The rest of the argumants are hosts */ argc -= optind; argv += optind; /* Setup timeout thread, if there is one */ if (program_timeout) { if (pthread_create(&thread_id, NULL, timeout_thread, NULL)) { fprintf(stderr,"Error: couldn't create program_timeout() thread\n"); exit(1); } } /* Setup tad for netfinger() threads */ if (pthread_tad_init(&netfinger_tad, max_count)) { fprintf(stderr,"Error: couldn't create netfinger() TAD.\n"); exit(1); } /* Setup the net and let everyone run */ netsetup(); while (*argv) { if (pthread_tad_create(&netfinger_tad, &thread_id, NULL, netfinger, *argv)) { fprintf(stderr, "Error: pthread_tad_create() netfinger_tad.\n"); exit(2); } argv++; } pthread_tad_wait(&parse_file_tad, 0); pthread_tad_wait(&netfinger_tad, 0); exit(0); }