Browse Source

Make shutdown more robust.

Enable the input thread only after the other threads exist.
Don't kill off the workio thread and use it to exit main() only if there is an unexpected problem.
Use kill_work() for all anticipated shutdowns where possible.
Remove unused thread entry.
nfactor-troky
Con Kolivas 13 years ago
parent
commit
37374bb44b
  1. 87
      cgminer.c

87
cgminer.c

@ -1589,6 +1589,7 @@ static void disable_curses(void)
static void print_summary(void); static void print_summary(void);
/* This should be the common exit path */
void kill_work(void) void kill_work(void)
{ {
struct thr_info *thr; struct thr_info *thr;
@ -1623,15 +1624,12 @@ void kill_work(void)
if (have_longpoll) if (have_longpoll)
thr_info_cancel(thr); thr_info_cancel(thr);
if (opt_debug)
applog(LOG_DEBUG, "Killing off work thread");
thr = &thr_info[work_thr_id];
thr_info_cancel(thr);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "Killing off API thread"); applog(LOG_DEBUG, "Killing off API thread");
thr = &thr_info[api_thr_id]; thr = &thr_info[api_thr_id];
thr_info_cancel(thr); thr_info_cancel(thr);
quit(0, "Shutdown signal received.");
} }
void quit(int status, const char *format, ...); void quit(int status, const char *format, ...);
@ -1642,8 +1640,6 @@ static void sighandler(int sig)
sigaction(SIGTERM, &termhandler, NULL); sigaction(SIGTERM, &termhandler, NULL);
sigaction(SIGINT, &inthandler, NULL); sigaction(SIGINT, &inthandler, NULL);
kill_work(); kill_work();
quit(sig, "Received interrupt signal.");
} }
static void *get_work_thread(void *userdata) static void *get_work_thread(void *userdata)
@ -2651,6 +2647,7 @@ static void *input_thread(void __maybe_unused *userdata)
return NULL; return NULL;
} }
/* This thread should not be shut down unless a problem occurs */
static void *workio_thread(void *userdata) static void *workio_thread(void *userdata)
{ {
struct thr_info *mythr = userdata; struct thr_info *mythr = userdata;
@ -3783,15 +3780,29 @@ static void print_summary(void)
quit(1, "Did not successfully mine as many shares as were requested."); quit(1, "Did not successfully mine as many shares as were requested.");
} }
void quit(int status, const char *format, ...) static void clean_up(void)
{ {
va_list ap; gettimeofday(&total_tv_end, NULL);
disable_curses(); disable_curses();
if (!opt_realquiet && successful_connect) if (!opt_realquiet && successful_connect)
print_summary(); print_summary();
#ifdef HAVE_OPENCL
clear_adl(nDevs);
#endif
if (opt_n_threads)
free(cpus);
curl_global_cleanup();
}
void quit(int status, const char *format, ...)
{
va_list ap;
clean_up();
if (format) { if (format) {
va_start(ap, format); va_start(ap, format);
vfprintf(stderr, format, ap); vfprintf(stderr, format, ap);
@ -4235,7 +4246,7 @@ int main (int argc, char *argv[])
fork_monitor(); fork_monitor();
#endif // defined(unix) #endif // defined(unix)
total_threads = mining_threads + 8; total_threads = mining_threads + 7;
work_restart = calloc(total_threads, sizeof(*work_restart)); work_restart = calloc(total_threads, sizeof(*work_restart));
if (!work_restart) if (!work_restart)
quit(1, "Failed to calloc work_restart"); quit(1, "Failed to calloc work_restart");
@ -4393,28 +4404,8 @@ retry_pools:
if (thr_info_create(thr, NULL, watchdog_thread, NULL)) if (thr_info_create(thr, NULL, watchdog_thread, NULL))
quit(1, "wakeup thread create failed"); quit(1, "wakeup thread create failed");
/* Create curses input thread for keyboard input */
input_thr_id = mining_threads + 4;
thr = &thr_info[input_thr_id];
if (thr_info_create(thr, NULL, input_thread, thr))
quit(1, "input thread create failed");
pthread_detach(thr->pth);
#if 0
#ifdef WANT_CPUMINE
/* Create reinit cpu thread */
cpur_thr_id = mining_threads + 5;
thr = &thr_info[cpur_thr_id];
thr->q = tq_new();
if (!thr->q)
quit(1, "tq_new failed for cpur_thr_id");
if (thr_info_create(thr, NULL, reinit_cpu, thr))
quit(1, "reinit_cpu thread create failed");
#endif
#endif
/* Create reinit gpu thread */ /* Create reinit gpu thread */
gpur_thr_id = mining_threads + 6; gpur_thr_id = mining_threads + 4;
thr = &thr_info[gpur_thr_id]; thr = &thr_info[gpur_thr_id];
thr->q = tq_new(); thr->q = tq_new();
if (!thr->q) if (!thr->q)
@ -4423,30 +4414,30 @@ retry_pools:
quit(1, "reinit_gpu thread create failed"); quit(1, "reinit_gpu thread create failed");
/* Create API socket thread */ /* Create API socket thread */
api_thr_id = mining_threads + 7; api_thr_id = mining_threads + 5;
thr = &thr_info[api_thr_id]; thr = &thr_info[api_thr_id];
if (thr_info_create(thr, NULL, api_thread, thr)) if (thr_info_create(thr, NULL, api_thread, thr))
quit(1, "API thread create failed"); quit(1, "API thread create failed");
pthread_detach(thr->pth); pthread_detach(thr->pth);
sleep(opt_log_interval); /* Create curses input thread for keyboard input. Create this last so
* that we know all threads are created since this can call kill_work
* to try and shut down ll previous threads. */
input_thr_id = mining_threads + 6;
thr = &thr_info[input_thr_id];
if (thr_info_create(thr, NULL, input_thread, thr))
quit(1, "input thread create failed");
pthread_detach(thr->pth);
/* main loop - simply wait for workio thread to exit */ /* main loop - simply wait for workio thread to exit. This is not the
* normal exit path and only occurs should the workio_thread die
* unexpectedly */
pthread_join(thr_info[work_thr_id].pth, NULL); pthread_join(thr_info[work_thr_id].pth, NULL);
applog(LOG_INFO, "workio thread dead, exiting."); applog(LOG_INFO, "workio thread dead, exiting.");
gettimeofday(&total_tv_end, NULL); clean_up();
disable_curses();
if (!opt_realquiet && successful_connect)
print_summary();
#ifdef HAVE_OPENCL
clear_adl(nDevs);
#endif
if (opt_n_threads)
free(cpus);
/* Not really necessary, but let's clean this up too anyway */
HASH_ITER(hh, staged_work, work, tmpwork) { HASH_ITER(hh, staged_work, work, tmpwork) {
HASH_DEL(staged_work, work); HASH_DEL(staged_work, work);
free_work(work); free_work(work);
@ -4456,7 +4447,5 @@ retry_pools:
free(block); free(block);
} }
curl_global_cleanup();
return 0; return 0;
} }

Loading…
Cancel
Save