int main( int argc, char **argval ) { JOB_DATA job_data; long long cnt = 0; signal( SIGINT, sig_int_handler ); #ifndef _HAVE_MSG_NOSIGNAL_ signal( SIGPIPE, SIG_IGN ); #endif parse_cmd_line( argc, argval, &job_data ); create_payload( &job_data ); if ( job_data.verbose ) { print_job_data( job_data ); } /* if */ cnt = flood_forked( job_data ); //printf( "%s[%d]: Sent %lld packets.\n\n", APPNAME, (int)getpid(), cnt ); free_job_data( &job_data ); drop_hash(); return cnt > 0; } /* main */
void free_joblist(struct s_client *cl) { pthread_mutex_trylock(&cl->thread_lock); LL_ITER it = ll_iter_create(cl->joblist); struct job_data *data; while((data = ll_iter_next(&it))) { free_job_data(data); } ll_destroy(cl->joblist); cl->joblist = NULL; cl->account = NULL; if(cl->work_job_data) // Free job_data that was not freed by work_thread { free_job_data(cl->work_job_data); } cl->work_job_data = NULL; pthread_mutex_unlock(&cl->thread_lock); pthread_mutex_destroy(&cl->thread_lock); }
void free_joblist(struct s_client *cl) { int32_t lock_status = pthread_mutex_trylock(&cl->thread_lock); LL_ITER it = ll_iter_create(cl->joblist); struct job_data *data; while((data = ll_iter_next(&it))) { free_job_data(data); } ll_destroy(&cl->joblist); cl->account = NULL; if(cl->work_job_data) // Free job_data that was not freed by work_thread { free_job_data(cl->work_job_data); } cl->work_job_data = NULL; if(lock_status == 0) { SAFE_MUTEX_UNLOCK(&cl->thread_lock); } pthread_mutex_destroy(&cl->thread_lock); }
/** * adds a job to the job queue * if ptr should be free() after use, set len to the size * else set size to 0 **/ int32_t add_job(struct s_client *cl, enum actions action, void *ptr, int32_t len) { if(!cl || cl->kill) { if(!cl) { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients if(len && ptr) { NULLFREE(ptr); } return 0; } #ifdef CS_CACHEEX // Avoid full running queues: if(action == ACTION_CACHE_PUSH_OUT && ll_count(cl->joblist) > 2000) { cs_debug_mask(D_TRACE, "WARNING: job queue %s %s has more than 2000 jobs! count=%d, dropped!", cl->typ == 'c' ? "client" : "reader", username(cl), ll_count(cl->joblist)); if(len && ptr) { NULLFREE(ptr); } // Thread down??? pthread_mutex_lock(&cl->thread_lock); if(cl && !cl->kill && cl->thread && cl->thread_active) { // Just test for invalid thread id: if(pthread_detach(cl->thread) == ESRCH) { cl->thread_active = 0; cs_debug_mask(D_TRACE, "WARNING: %s %s thread died!", cl->typ == 'c' ? "client" : "reader", username(cl)); } } pthread_mutex_unlock(&cl->thread_lock); return 0; } #endif struct job_data *data; if(!cs_malloc(&data, sizeof(struct job_data))) { if(len && ptr) { NULLFREE(ptr); } return 0; } data->action = action; data->ptr = ptr; data->cl = cl; data->len = len; cs_ftime(&data->time); pthread_mutex_lock(&cl->thread_lock); if(cl && !cl->kill && cl->thread_active) { if(!cl->joblist) { cl->joblist = ll_create("joblist"); } ll_append(cl->joblist, data); if(cl->thread_active == 2) { pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP); } pthread_mutex_unlock(&cl->thread_lock); cs_debug_mask(D_TRACE, "add %s job action %d queue length %d %s", action > ACTION_CLIENT_FIRST ? "client" : "reader", action, ll_count(cl->joblist), username(cl)); return 1; } pthread_attr_t attr; pthread_attr_init(&attr); /* pcsc doesn't like this either; segfaults on x86, x86_64 */ struct s_reader *rdr = cl->reader; if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC) { pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE); } if(action != ACTION_READER_CHECK_HEALTH) { cs_debug_mask(D_TRACE, "start %s thread action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action); } int32_t ret = pthread_create(&cl->thread, &attr, work_thread, (void *)data); if(ret) { cs_log("ERROR: can't create thread for %s (errno=%d %s)", action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret)); free_job_data(data); } else { pthread_detach(cl->thread); } pthread_attr_destroy(&attr); cl->thread_active = 1; pthread_mutex_unlock(&cl->thread_lock); return 1; }
/** * adds a job to the job queue * if ptr should be free() after use, set len to the size * else set size to 0 **/ int32_t add_job(struct s_client *cl, enum actions action, void *ptr, int32_t len) { if(!cl || cl->kill) { if(!cl) { cs_log("WARNING: add_job failed. Client killed!"); } // Ignore jobs for killed clients if(len && ptr) { NULLFREE(ptr); } return 0; } if(action == ACTION_CACHE_PUSH_OUT && cacheex_check_queue_length(cl)) { if(len && ptr) { NULLFREE(ptr); } return 0; } struct job_data *data; if(!cs_malloc(&data, sizeof(struct job_data))) { if(len && ptr) { NULLFREE(ptr); } return 0; } data->action = action; data->ptr = ptr; data->cl = cl; data->len = len; cs_ftime(&data->time); SAFE_MUTEX_LOCK(&cl->thread_lock); if(cl && !cl->kill && cl->thread_active) { if(!cl->joblist) { cl->joblist = ll_create("joblist"); } ll_append(cl->joblist, data); if(cl->thread_active == 2) { pthread_kill(cl->thread, OSCAM_SIGNAL_WAKEUP); } SAFE_MUTEX_UNLOCK(&cl->thread_lock); cs_log_dbg(D_TRACE, "add %s job action %d queue length %d %s", action > ACTION_CLIENT_FIRST ? "client" : "reader", action, ll_count(cl->joblist), username(cl)); return 1; } /* pcsc doesn't like this; segfaults on x86, x86_64 */ int8_t modify_stacksize = 0; struct s_reader *rdr = cl->reader; if(cl->typ != 'r' || !rdr || rdr->typ != R_PCSC) { modify_stacksize = 1; } if(action != ACTION_READER_CHECK_HEALTH) { cs_log_dbg(D_TRACE, "start %s thread action %d", action > ACTION_CLIENT_FIRST ? "client" : "reader", action); } int32_t ret = start_thread("client work", work_thread, (void *)data, &cl->thread, 1, modify_stacksize); if(ret) { cs_log("ERROR: can't create thread for %s (errno=%d %s)", action > ACTION_CLIENT_FIRST ? "client" : "reader", ret, strerror(ret)); free_job_data(data); } cl->thread_active = 1; SAFE_MUTEX_UNLOCK(&cl->thread_lock); return 1; }