pthreads - zombie threads on AIX 6.1 -
pthreads - zombie threads on AIX 6.1 -
i having issues on aix 6.1 1 time thread created appears not die.
compile with: gcc -pthread sample.c cc_r sample.c
both have same result.
i have attempted detach thread in 3 ways. 1) main method calls pthread_detach after created. 2) main method attempts create thread detached through attr arg. 3) thread function calling pthread_detach.
my attempts track thread start/stop result in threads finishing.
all 3 per phone call have numerous threads in state z
-bash-4.2# ps -mo thread -p `ps -ef | grep a.out | awk '{print $2}'` user pid ppid tid st cp pri sc wchan f tt bnd command root 340028 278750 - 0 60 11 f100010019c574b0 200001 pts/0 - ./a.out 10 3 - - - 450679 z 0 60 1 - c00001 - - - - - - 561215 z 0 60 1 - c00001 - - - - - - 573523 z 0 60 1 - c00001 - - - - - - 663653 z 0 60 1 - c00001 - - - - - - 684203 z 0 60 1 - c00001 - - - - - - 745711 z 0 60 1 - c00001 - - - - - - 753695 z 0 60 1 - c00001 - - - - - - 987139 z 0 60 1 - c00001 - - - - - - 1007867 z 0 60 1 - c00001 - - - - - - 1523761 s 0 60 1 f100010019c574b0 410400 - - - - - - 1536067 z 0 60 1 - c00001 - - -
here code (i know sloppy! please excuse!)
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <pthread.h> #include <limits.h> #define detach_none 0 #define detach_method_detach_in_main 1 #define detach_at_pthread_create 2 #define detach_in_thread_func 3 int g_ndetachmethod = detach_method_detach_in_main; void increment_count(); void decrement_count(); long long get_count(); void set_count( long long c ); void *printhello2( void* ptr ); void displaythreadstatus( pthread_t tid ); void displaytopoutput(); void *printhello2( void* ptr ) { int rc; pthread_t tid = pthread_self(); sched_yield(); increment_count(); sleep( rand() % 10 + 1 ); displaythreadstatus( tid ); if( g_ndetachmethod == detach_in_thread_func ) { rc = pthread_detach( tid ); printf("\t\tdetach result: %d.\n", rc); displaythreadstatus( tid ); } decrement_count(); pthread_exit (null); } int main( int argc, char *argv[] ) { pthread_t thds; int i, count, num_threads, rc; set_count( 0 ); if( argc < 2 ) { printf("specify on command line detach method utilize , number of threads.\n"); printf("usage: %s threads detachmethod\n", argv[0]); printf("\t threads: count of kid threads spawn. default=10\n"); printf("\tdetachmethod: point @ detach should called. default=%d\n", detach_method_detach_in_main); printf("\t\t\t%d: not effort detach. default behaviour joinable.\n"); printf("\t\t\t%d: phone call pthread_detach right after pthread_create in main.\n", detach_method_detach_in_main); printf("\t\t\t%d: phone call pthread_create pthread_attr_setdetachstate attribute set pthread_create_detached.\n", detach_at_pthread_create); printf("\t\t\t%d: phone call pthread_detach within thread function.\n", detach_in_thread_func); printf("\nexample:\n"); printf("\t a.out 10 %d\n", detach_method_detach_in_main); exit(0); } printf("using threads:\"%s\" detach method:\"%s\"\n", argv[1], argv[2]); num_threads = atoi( argv[1] ); g_ndetachmethod = atoi( argv[2] ); printf("\n\n======= creating %d threads =======\n", num_threads); for( = 0; < num_threads; i++ ) { printf( "\n\tcreating thread : %d \n", ); if( g_ndetachmethod == detach_at_pthread_create ) { pthread_attr_t tattr; pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr,pthread_create_detached); pthread_create( &thds, &tattr, printhello2, (void*) null ); } else { pthread_create( &thds, null, printhello2, (void*) null ); if( g_ndetachmethod == detach_method_detach_in_main ) { rc = pthread_detach( thds ); printf("\t\tdetach result: %d.\n", rc); } } } printf("\n\n======= waiting threads finish =======\n"); for( = 0; < 20; i++ ) { sleep( 1 ); count = get_count(); printf( "\tloop: %d, active threads: %d, sleep seconds: %d\n", i, count, (i + 1) ); if( count == 0 ) break; } displaytopoutput(); printf("\n\n======= waiting 10 seconds manually query defunct processes =======\n"); printf("ps -mo thread -p `ps -ef | grep a.out | awk '{print $2}'`\n"); for( = 10; >= 0; i-- ) { sleep( 1 ); printf( "\r%d seconds remaining.", ); fflush (stdout); } count = get_count(); printf("\n\n======= final status active threads: %d =======\n", count ); displaytopoutput(); homecoming 0; } void displaythreadstatus( pthread_t tid ) { /* int state; pthread_attr_t attr; pthread_getattr_np( pthread_self(), &attr); pthread_attr_getdetachstate( &attr, &state ); printf("\t\t[%d]: %s\n", tid, state == pthread_create_detached? "pthread_create_detached": "pthread_create_joinable"); */ } void displaytopoutput() { if( fork() != 0 ) { int status; wait( &status ); return; } pid_t pid = getppid(); char buffer[10]; sprintf( buffer, "%d", (int) pid ); printf( "pid: %s\n", buffer ); /* execl( "/usr/bin/top", "top", "-h", "-b", "-n", "1", "-d", "1", "-p", buffer, (char *) null ); */ execl("/usr/bin/ps", "ps", "-mo", "thread", "-p", buffer, (char *) null ); printf("\n"); exit( 0 ); } pthread_mutex_t count_mutex; long long count=0; void increment_count() { pthread_mutex_lock( &count_mutex ); count = count + 1; pthread_mutex_unlock( &count_mutex ); } void decrement_count() { pthread_mutex_lock( &count_mutex ); count = count - 1; pthread_mutex_unlock( &count_mutex ); } long long get_count() { long long c; pthread_mutex_lock( &count_mutex ); c = count; pthread_mutex_unlock( &count_mutex ); homecoming (c); } void set_count( long long c ) { pthread_mutex_lock( &count_mutex ); count = c; pthread_mutex_unlock( &count_mutex ); }
i quote article describing pthreads implementation on aix:
the kernel maintains list, called deathrow, of lwps , kernel threads have exited, in order reap terminated lwp/kthread when new 1 needs created (fork()). if lwp/kthread available on list of zombies, kernel not need allocate info structures , stack new kthread; uses structures , stack zombie kthread , links kthread process issued fork(2) (or thread_create()) command.
in process creation flow, when forklwp() code calls lwp_create(), lwp_create() first looks on deathrow zombie thread. if 1 exists, lwp, kthread, , stack linked process, , kernel spared need allocate new kthread, lwp, , stack space during fork() process. kernel grabs structures deathrow list, links pointers appropriately, , moves on. thread_create() (kernel thread create, not user thread api), called lwp_create() passed lwp info , stack , avoids doing kernel memory allocations.
full article here: http://flylib.com/books/en/2.830.1.30/1/
pthreads
Comments
Post a Comment