Merge pull request #268 from chme/threadexit

Refactor thread exit handling
This commit is contained in:
ejurgensen 2016-06-11 22:57:09 +02:00 committed by GitHub
commit 547783d008
8 changed files with 71 additions and 341 deletions

View File

@ -72,8 +72,6 @@ static pthread_t tid_cache;
// Event base, pipes and events // Event base, pipes and events
struct event_base *evbase_cache; struct event_base *evbase_cache;
static int g_exit_pipe[2];
static struct event *g_exitev;
static struct event *g_cacheev; static struct event *g_cacheev;
static struct commands_base *cmdbase; static struct commands_base *cmdbase;
@ -123,18 +121,6 @@ remove_tag(char *in, const char *tag)
} }
static void
thread_exit(void)
{
int dummy = 42;
DPRINTF(E_DBG, L_CACHE, "Killing cache thread\n");
if (write(g_exit_pipe[1], &dummy, sizeof(dummy)) != sizeof(dummy))
DPRINTF(E_LOG, L_CACHE, "Could not write to exit fd: %s\n", strerror(errno));
}
/* --------------------------------- MAIN --------------------------------- */ /* --------------------------------- MAIN --------------------------------- */
/* Thread: cache */ /* Thread: cache */
@ -1316,23 +1302,6 @@ cache(void *arg)
pthread_exit(NULL); pthread_exit(NULL);
} }
static void
exit_cb(int fd, short what, void *arg)
{
int dummy;
int ret;
ret = read(g_exit_pipe[0], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_CACHE, "Error reading from exit pipe\n");
event_base_loopbreak(evbase_cache);
g_initialized = 0;
event_add(g_exitev, NULL);
}
/* ---------------------------- DAAP cache API --------------------------- */ /* ---------------------------- DAAP cache API --------------------------- */
@ -1637,17 +1606,6 @@ cache_init(void)
return 0; return 0;
} }
#ifdef HAVE_PIPE2
ret = pipe2(g_exit_pipe, O_CLOEXEC);
#else
ret = pipe(g_exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_CACHE, "Could not create exit pipe: %s\n", strerror(errno));
goto exit_fail;
}
evbase_cache = event_base_new(); evbase_cache = event_base_new();
if (!evbase_cache) if (!evbase_cache)
{ {
@ -1655,13 +1613,6 @@ cache_init(void)
goto evbase_fail; goto evbase_fail;
} }
g_exitev = event_new(evbase_cache, g_exit_pipe[0], EV_READ, exit_cb, NULL);
if (!g_exitev)
{
DPRINTF(E_LOG, L_CACHE, "Could not create exit event\n");
goto evnew_fail;
}
g_cacheev = evtimer_new(evbase_cache, cache_daap_update_cb, NULL); g_cacheev = evtimer_new(evbase_cache, cache_daap_update_cb, NULL);
if (!g_cacheev) if (!g_cacheev)
{ {
@ -1669,9 +1620,7 @@ cache_init(void)
goto evnew_fail; goto evnew_fail;
} }
event_add(g_exitev, NULL); cmdbase = commands_base_new(evbase_cache, NULL);
cmdbase = commands_base_new(evbase_cache);
DPRINTF(E_INFO, L_CACHE, "cache thread init\n"); DPRINTF(E_INFO, L_CACHE, "cache thread init\n");
@ -1698,10 +1647,6 @@ cache_init(void)
evbase_cache = NULL; evbase_cache = NULL;
evbase_fail: evbase_fail:
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
exit_fail:
return -1; return -1;
} }
@ -1713,7 +1658,8 @@ cache_deinit(void)
if (!g_initialized) if (!g_initialized)
return; return;
thread_exit(); g_initialized = 0;
commands_base_destroy(cmdbase);
ret = pthread_join(tid_cache, NULL); ret = pthread_join(tid_cache, NULL);
if (ret != 0) if (ret != 0)
@ -1724,9 +1670,4 @@ cache_deinit(void)
// Free event base (should free events too) // Free event base (should free events too)
event_base_free(evbase_cache); event_base_free(evbase_cache);
// Close pipes and free command base
commands_base_free(cmdbase);
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
} }

View File

@ -46,6 +46,8 @@ struct command
struct commands_base struct commands_base
{ {
struct event_base *evbase;
command_exit_cb exit_cb;
int command_pipe[2]; int command_pipe[2];
struct event *command_event; struct event *command_event;
struct command *current_cmd; struct command *current_cmd;
@ -166,10 +168,13 @@ send_command(struct commands_base *cmdbase, struct command *cmd)
} }
/* /*
* Creates a new command base, needs to be freed by commands_base_free. * Creates a new command base, needs to be freed by commands_base_destroy or commands_base_free.
*
* @param evbase The libevent base to use for command handling
* @param exit_cb Callback function to be called during commands_base_destroy
*/ */
struct commands_base * struct commands_base *
commands_base_new(struct event_base *evbase) commands_base_new(struct event_base *evbase, command_exit_cb exit_cb)
{ {
struct commands_base *cmdbase; struct commands_base *cmdbase;
int ret; int ret;
@ -213,6 +218,9 @@ commands_base_new(struct event_base *evbase)
return NULL; return NULL;
} }
cmdbase->evbase = evbase;
cmdbase->exit_cb = exit_cb;
return cmdbase; return cmdbase;
} }
@ -359,3 +367,39 @@ commands_exec_async(struct commands_base *cmdbase, command_function func, void *
return 0; return 0;
} }
/*
* Command to break the libevent loop
*
* If the command base was created with an exit_cb function, exit_cb is called before breaking the
* libevent loop.
*
* @param arg The command base
* @param retval Always set to COMMAND_END
*/
static enum command_state
cmdloop_exit(void *arg, int *retval)
{
struct commands_base *cmdbase = arg;
*retval = 0;
if (cmdbase->exit_cb)
cmdbase->exit_cb();
event_base_loopbreak(cmdbase->evbase);
return COMMAND_END;
}
/*
* Break the libevent loop for the given command base, closes the internally used pipes
* and frees the command base.
*
* @param cmdbase The command base
*/
void
commands_base_destroy(struct commands_base *cmdbase)
{
commands_exec_sync(cmdbase, cmdloop_exit, NULL, cmdbase);
commands_base_free(cmdbase);
}

View File

@ -39,11 +39,14 @@ enum command_state {
*/ */
typedef enum command_state (*command_function)(void *arg, int *ret); typedef enum command_state (*command_function)(void *arg, int *ret);
typedef void (*command_exit_cb)(void);
struct commands_base; struct commands_base;
struct commands_base * struct commands_base *
commands_base_new(struct event_base *evbase); commands_base_new(struct event_base *evbase, command_exit_cb exit_cb);
int int
commands_base_free(struct commands_base *cmdbase); commands_base_free(struct commands_base *cmdbase);
@ -60,5 +63,7 @@ commands_exec_sync(struct commands_base *cmdbase, command_function func, command
int int
commands_exec_async(struct commands_base *cmdbase, command_function func, void *arg); commands_exec_async(struct commands_base *cmdbase, command_function func, void *arg);
void
commands_base_destroy(struct commands_base *cmdbase);
#endif /* SRC_COMMANDS_H_ */ #endif /* SRC_COMMANDS_H_ */

View File

@ -104,12 +104,10 @@ struct stacked_dir {
struct stacked_dir *next; struct stacked_dir *next;
}; };
static int exit_pipe[2];
static int scan_exit; static int scan_exit;
static int inofd; static int inofd;
static struct event_base *evbase_scan; static struct event_base *evbase_scan;
static struct event *inoev; static struct event *inoev;
static struct event *exitev;
static pthread_t tid_scan; static pthread_t tid_scan;
static struct deferred_pl *playlists; static struct deferred_pl *playlists;
static struct stacked_dir *dirstack; static struct stacked_dir *dirstack;
@ -1911,13 +1909,6 @@ inofd_event_unset(void)
} }
/* Thread: scan */ /* Thread: scan */
static void
exit_cb(int fd, short event, void *arg)
{
event_base_loopbreak(evbase_scan);
scan_exit = 1;
}
static enum command_state static enum command_state
filescanner_initscan(void *arg, int *retval) filescanner_initscan(void *arg, int *retval)
@ -2002,32 +1993,13 @@ filescanner_init(void)
return -1; return -1;
} }
#ifdef HAVE_PIPE2
ret = pipe2(exit_pipe, O_CLOEXEC);
#else
ret = pipe(exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_FATAL, L_SCAN, "Could not create pipe: %s\n", strerror(errno));
goto pipe_fail;
}
exitev = event_new(evbase_scan, exit_pipe[0], EV_READ, exit_cb, NULL);
if (!exitev || (event_add(exitev, NULL) < 0))
{
DPRINTF(E_LOG, L_SCAN, "Could not create/add command event\n");
goto exitev_fail;
}
ret = inofd_event_set(); ret = inofd_event_set();
if (ret < 0) if (ret < 0)
{ {
goto ino_fail; goto ino_fail;
} }
cmdbase = commands_base_new(evbase_scan); cmdbase = commands_base_new(evbase_scan, NULL);
ret = pthread_create(&tid_scan, NULL, filescanner, NULL); ret = pthread_create(&tid_scan, NULL, filescanner, NULL);
if (ret != 0) if (ret != 0)
@ -2048,11 +2020,7 @@ filescanner_init(void)
thread_fail: thread_fail:
commands_base_free(cmdbase); commands_base_free(cmdbase);
close(inofd); close(inofd);
exitev_fail:
ino_fail: ino_fail:
close(exit_pipe[0]);
close(exit_pipe[1]);
pipe_fail:
event_base_free(evbase_scan); event_base_free(evbase_scan);
return -1; return -1;
@ -2063,17 +2031,9 @@ void
filescanner_deinit(void) filescanner_deinit(void)
{ {
int ret; int ret;
int dummy = 42;
ret = write(exit_pipe[1], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
{
DPRINTF(E_FATAL, L_SCAN, "Could not write to exit fd: %s\n", strerror(errno));
return;
}
scan_exit = 1; scan_exit = 1;
commands_base_destroy(cmdbase);
ret = pthread_join(tid_scan, NULL); ret = pthread_join(tid_scan, NULL);
if (ret != 0) if (ret != 0)
@ -2086,7 +2046,4 @@ filescanner_deinit(void)
inofd_event_unset(); inofd_event_unset();
event_base_free(evbase_scan); event_base_free(evbase_scan);
commands_base_free(cmdbase);
close(exit_pipe[0]);
close(exit_pipe[1]);
} }

View File

@ -68,8 +68,6 @@
static pthread_t tid_mpd; static pthread_t tid_mpd;
static struct event_base *evbase_mpd; static struct event_base *evbase_mpd;
static int g_exit_pipe[2];
static struct event *g_exitev;
static struct commands_base *cmdbase; static struct commands_base *cmdbase;
@ -192,17 +190,6 @@ struct idle_client
struct idle_client *idle_clients; struct idle_client *idle_clients;
static void
thread_exit(void)
{
int dummy = 42;
DPRINTF(E_DBG, L_MPD, "Killing mpd thread\n");
if (write(g_exit_pipe[1], &dummy, sizeof(dummy)) != sizeof(dummy))
DPRINTF(E_LOG, L_MPD, "Could not write to exit fd: %s\n", strerror(errno));
}
/* Thread: mpd */ /* Thread: mpd */
static void * static void *
@ -225,21 +212,6 @@ mpd(void *arg)
pthread_exit(NULL); pthread_exit(NULL);
} }
static void
exit_cb(int fd, short what, void *arg)
{
int dummy;
int ret;
ret = read(g_exit_pipe[0], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_MPD, "Error reading from exit pipe\n");
event_base_loopbreak(evbase_mpd);
event_add(g_exitev, NULL);
}
static void static void
mpd_time(char *buffer, size_t bufferlen, time_t t) mpd_time(char *buffer, size_t bufferlen, time_t t)
{ {
@ -4670,17 +4642,6 @@ int mpd_init(void)
v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6"); v6enabled = cfg_getbool(cfg_getsec(cfg, "general"), "ipv6");
#ifdef HAVE_PIPE2
ret = pipe2(g_exit_pipe, O_CLOEXEC);
#else
ret = pipe(g_exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_MPD, "Could not create pipe: %s\n", strerror(errno));
goto exit_fail;
}
evbase_mpd = event_base_new(); evbase_mpd = event_base_new();
if (!evbase_mpd) if (!evbase_mpd)
{ {
@ -4688,16 +4649,7 @@ int mpd_init(void)
goto evbase_fail; goto evbase_fail;
} }
g_exitev = event_new(evbase_mpd, g_exit_pipe[0], EV_READ, exit_cb, NULL); cmdbase = commands_base_new(evbase_mpd, NULL);
if (!g_exitev)
{
DPRINTF(E_LOG, L_MPD, "Could not create exit event\n");
goto evnew_fail;
}
event_add(g_exitev, NULL);
cmdbase = commands_base_new(evbase_mpd);
if (v6enabled) if (v6enabled)
{ {
@ -4808,15 +4760,10 @@ int mpd_init(void)
evconnlistener_free(listener); evconnlistener_free(listener);
connew_fail: connew_fail:
commands_base_free(cmdbase); commands_base_free(cmdbase);
evnew_fail:
event_base_free(evbase_mpd); event_base_free(evbase_mpd);
evbase_mpd = NULL; evbase_mpd = NULL;
evbase_fail: evbase_fail:
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
exit_fail:
return -1; return -1;
} }
@ -4835,7 +4782,7 @@ void mpd_deinit(void)
return; return;
} }
thread_exit(); commands_base_destroy(cmdbase);
ret = pthread_join(tid_mpd, NULL); ret = pthread_join(tid_mpd, NULL);
if (ret != 0) if (ret != 0)
@ -4861,9 +4808,4 @@ void mpd_deinit(void)
// Free event base (should free events too) // Free event base (should free events too)
event_base_free(evbase_mpd); event_base_free(evbase_mpd);
// Close pipes and free command base
commands_base_free(cmdbase);
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
} }

View File

@ -220,9 +220,7 @@ union player_arg
struct event_base *evbase_player; struct event_base *evbase_player;
static int exit_pipe[2];
static int player_exit; static int player_exit;
static struct event *exitev;
static pthread_t tid_player; static pthread_t tid_player;
static struct commands_base *cmdbase; static struct commands_base *cmdbase;
@ -3952,14 +3950,6 @@ player(void *arg)
pthread_exit(NULL); pthread_exit(NULL);
} }
/* Thread: player */
static void
exit_cb(int fd, short what, void *arg)
{
event_base_loopbreak(evbase_player);
player_exit = 1;
}
/* Thread: main */ /* Thread: main */
int int
@ -4041,18 +4031,6 @@ player_init(void)
goto audio_fail; goto audio_fail;
} }
#ifdef HAVE_PIPE2
ret = pipe2(exit_pipe, O_CLOEXEC);
#else
ret = pipe(exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_PLAYER, "Could not create pipe: %s\n", strerror(errno));
goto exit_fail;
}
evbase_player = event_base_new(); evbase_player = event_base_new();
if (!evbase_player) if (!evbase_player)
{ {
@ -4061,13 +4039,6 @@ player_init(void)
goto evbase_fail; goto evbase_fail;
} }
exitev = event_new(evbase_player, exit_pipe[0], EV_READ, exit_cb, NULL);
if (!exitev)
{
DPRINTF(E_LOG, L_PLAYER, "Could not create exit event\n");
goto evnew_fail;
}
#if defined(__linux__) #if defined(__linux__)
pb_timer_ev = event_new(evbase_player, pb_timer_fd, EV_READ | EV_PERSIST, player_playback_cb, NULL); pb_timer_ev = event_new(evbase_player, pb_timer_fd, EV_READ | EV_PERSIST, player_playback_cb, NULL);
#else #else
@ -4079,10 +4050,9 @@ player_init(void)
goto evnew_fail; goto evnew_fail;
} }
event_add(exitev, NULL);
event_add(pb_timer_ev, NULL); event_add(pb_timer_ev, NULL);
cmdbase = commands_base_new(evbase_player); cmdbase = commands_base_new(evbase_player, NULL);
ret = outputs_init(); ret = outputs_init();
if (ret < 0) if (ret < 0)
@ -4112,9 +4082,6 @@ player_init(void)
evnew_fail: evnew_fail:
event_base_free(evbase_player); event_base_free(evbase_player);
evbase_fail: evbase_fail:
close(exit_pipe[0]);
close(exit_pipe[1]);
exit_fail:
evbuffer_free(audio_buf); evbuffer_free(audio_buf);
audio_fail: audio_fail:
#if defined(__linux__) #if defined(__linux__)
@ -4131,20 +4098,14 @@ void
player_deinit(void) player_deinit(void)
{ {
int ret; int ret;
int dummy = 42;
ret = write(exit_pipe[1], &dummy, sizeof(dummy)); player_exit = 1;
if (ret != sizeof(dummy)) commands_base_destroy(cmdbase);
{
DPRINTF(E_LOG, L_PLAYER, "Could not write to exit pipe: %s\n", strerror(errno));
return;
}
ret = pthread_join(tid_player, NULL); ret = pthread_join(tid_player, NULL);
if (ret != 0) if (ret != 0)
{ {
DPRINTF(E_LOG, L_PLAYER, "Could not join HTTPd thread: %s\n", strerror(errno)); DPRINTF(E_LOG, L_PLAYER, "Could not join player thread: %s\n", strerror(errno));
return; return;
} }
@ -4164,8 +4125,4 @@ player_deinit(void)
outputs_deinit(); outputs_deinit();
event_base_free(evbase_player); event_base_free(evbase_player);
commands_base_free(cmdbase);
close(exit_pipe[0]);
close(exit_pipe[1]);
} }

View File

@ -114,9 +114,7 @@ static pthread_cond_t login_cond;
// Event base, pipes and events // Event base, pipes and events
struct event_base *evbase_spotify; struct event_base *evbase_spotify;
static int g_exit_pipe[2];
static int g_notify_pipe[2]; static int g_notify_pipe[2];
static struct event *g_exitev;
static struct event *g_notifyev; static struct event *g_notifyev;
static struct commands_base *cmdbase; static struct commands_base *cmdbase;
@ -384,21 +382,6 @@ fptr_assign_all()
// End of ugly part // End of ugly part
/* ---------------------------- COMMAND EXECUTION -------------------------- */
/* Thread: main and filescanner */
static void
thread_exit(void)
{
int dummy = 42;
DPRINTF(E_DBG, L_SPOTIFY, "Killing Spotify thread\n");
if (write(g_exit_pipe[1], &dummy, sizeof(dummy)) != sizeof(dummy))
DPRINTF(E_LOG, L_SPOTIFY, "Could not write to exit fd: %s\n", strerror(errno));
}
/* -------------------------- PLAYLIST HELPERS ------------------------- */ /* -------------------------- PLAYLIST HELPERS ------------------------- */
/* Should only be called from within the spotify thread */ /* Should only be called from within the spotify thread */
@ -1619,23 +1602,11 @@ spotify(void *arg)
} }
static void static void
exit_cb(int fd, short what, void *arg) exit_cb()
{ {
int dummy;
int ret;
ret = read(g_exit_pipe[0], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_SPOTIFY, "Error reading from exit pipe\n");
fptr_sp_session_player_unload(g_sess); fptr_sp_session_player_unload(g_sess);
fptr_sp_session_logout(g_sess); fptr_sp_session_logout(g_sess);
event_base_loopbreak(evbase_spotify);
g_state = SPOTIFY_STATE_INACTIVE; g_state = SPOTIFY_STATE_INACTIVE;
event_add(g_exitev, NULL);
} }
/* Process events when timeout expires or triggered by libspotify's notify_main_thread */ /* Process events when timeout expires or triggered by libspotify's notify_main_thread */
@ -1976,17 +1947,6 @@ spotify_init(void)
if (ret < 0) if (ret < 0)
goto assign_fail; goto assign_fail;
#ifdef HAVE_PIPE2
ret = pipe2(g_exit_pipe, O_CLOEXEC);
#else
ret = pipe(g_exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_SPOTIFY, "Could not create pipe: %s\n", strerror(errno));
goto exit_fail;
}
#ifdef HAVE_PIPE2 #ifdef HAVE_PIPE2
ret = pipe2(g_notify_pipe, O_CLOEXEC); ret = pipe2(g_notify_pipe, O_CLOEXEC);
#else #else
@ -2005,13 +1965,6 @@ spotify_init(void)
goto evbase_fail; goto evbase_fail;
} }
g_exitev = event_new(evbase_spotify, g_exit_pipe[0], EV_READ, exit_cb, NULL);
if (!g_exitev)
{
DPRINTF(E_LOG, L_SPOTIFY, "Could not create exit event\n");
goto evnew_fail;
}
g_notifyev = event_new(evbase_spotify, g_notify_pipe[0], EV_READ | EV_TIMEOUT, notify_cb, NULL); g_notifyev = event_new(evbase_spotify, g_notify_pipe[0], EV_READ | EV_TIMEOUT, notify_cb, NULL);
if (!g_notifyev) if (!g_notifyev)
{ {
@ -2019,11 +1972,10 @@ spotify_init(void)
goto evnew_fail; goto evnew_fail;
} }
event_add(g_exitev, NULL);
event_add(g_notifyev, NULL); event_add(g_notifyev, NULL);
cmdbase = commands_base_new(evbase_spotify); cmdbase = commands_base_new(evbase_spotify, exit_cb);
if (!cmdbase) if (!cmdbase)
{ {
DPRINTF(E_LOG, L_SPOTIFY, "Could not create command base\n"); DPRINTF(E_LOG, L_SPOTIFY, "Could not create command base\n");
@ -2116,10 +2068,6 @@ spotify_init(void)
close(g_notify_pipe[1]); close(g_notify_pipe[1]);
notify_fail: notify_fail:
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
exit_fail:
assign_fail: assign_fail:
dlclose(g_libhandle); dlclose(g_libhandle);
g_libhandle = NULL; g_libhandle = NULL;
@ -2139,7 +2087,8 @@ spotify_deinit(void)
/* Send exit signal to thread (if active) */ /* Send exit signal to thread (if active) */
if (g_state != SPOTIFY_STATE_INACTIVE) if (g_state != SPOTIFY_STATE_INACTIVE)
{ {
thread_exit(); commands_base_destroy(cmdbase);
g_state = SPOTIFY_STATE_INACTIVE;
ret = pthread_join(tid_spotify, NULL); ret = pthread_join(tid_spotify, NULL);
if (ret != 0) if (ret != 0)
@ -2155,12 +2104,9 @@ spotify_deinit(void)
/* Free event base (should free events too) */ /* Free event base (should free events too) */
event_base_free(evbase_spotify); event_base_free(evbase_spotify);
/* Close pipes and free command base */ /* Close pipes */
commands_base_free(cmdbase);
close(g_notify_pipe[0]); close(g_notify_pipe[0]);
close(g_notify_pipe[1]); close(g_notify_pipe[1]);
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
/* Destroy locks */ /* Destroy locks */
pthread_cond_destroy(&login_cond); pthread_cond_destroy(&login_cond);

View File

@ -58,8 +58,6 @@ static pthread_t tid_worker;
// Event base, pipes and events // Event base, pipes and events
struct event_base *evbase_worker; struct event_base *evbase_worker;
static int g_initialized; static int g_initialized;
static int g_exit_pipe[2];
static struct event *g_exitev;
static struct commands_base *cmdbase; static struct commands_base *cmdbase;
@ -102,20 +100,6 @@ execute(void *arg, int *retval)
} }
/* Thread: main */
static void
thread_exit(void)
{
int dummy = 42;
DPRINTF(E_DBG, L_MAIN, "Killing worker thread\n");
if (write(g_exit_pipe[1], &dummy, sizeof(dummy)) != sizeof(dummy))
DPRINTF(E_LOG, L_MAIN, "Could not write to exit fd: %s\n", strerror(errno));
}
/* --------------------------------- MAIN --------------------------------- */ /* --------------------------------- MAIN --------------------------------- */
/* Thread: worker */ /* Thread: worker */
@ -146,23 +130,6 @@ worker(void *arg)
pthread_exit(NULL); pthread_exit(NULL);
} }
static void
exit_cb(int fd, short what, void *arg)
{
int dummy;
int ret;
ret = read(g_exit_pipe[0], &dummy, sizeof(dummy));
if (ret != sizeof(dummy))
DPRINTF(E_LOG, L_MAIN, "Error reading from exit pipe\n");
event_base_loopbreak(evbase_worker);
g_initialized = 0;
event_add(g_exitev, NULL);
}
/* ---------------------------- Our worker API --------------------------- */ /* ---------------------------- Our worker API --------------------------- */
@ -205,17 +172,6 @@ worker_init(void)
{ {
int ret; int ret;
#ifdef HAVE_PIPE2
ret = pipe2(g_exit_pipe, O_CLOEXEC);
#else
ret = pipe(g_exit_pipe);
#endif
if (ret < 0)
{
DPRINTF(E_LOG, L_MAIN, "Could not create pipe: %s\n", strerror(errno));
goto exit_fail;
}
evbase_worker = event_base_new(); evbase_worker = event_base_new();
if (!evbase_worker) if (!evbase_worker)
{ {
@ -223,16 +179,7 @@ worker_init(void)
goto evbase_fail; goto evbase_fail;
} }
g_exitev = event_new(evbase_worker, g_exit_pipe[0], EV_READ, exit_cb, NULL); cmdbase = commands_base_new(evbase_worker, NULL);
if (!g_exitev)
{
DPRINTF(E_LOG, L_MAIN, "Could not create exit event\n");
goto evnew_fail;
}
cmdbase = commands_base_new(evbase_worker);
event_add(g_exitev, NULL);
ret = pthread_create(&tid_worker, NULL, worker, NULL); ret = pthread_create(&tid_worker, NULL, worker, NULL);
if (ret < 0) if (ret < 0)
@ -252,15 +199,10 @@ worker_init(void)
thread_fail: thread_fail:
commands_base_free(cmdbase); commands_base_free(cmdbase);
evnew_fail:
event_base_free(evbase_worker); event_base_free(evbase_worker);
evbase_worker = NULL; evbase_worker = NULL;
evbase_fail: evbase_fail:
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
exit_fail:
return -1; return -1;
} }
@ -269,7 +211,8 @@ worker_deinit(void)
{ {
int ret; int ret;
thread_exit(); g_initialized = 0;
commands_base_destroy(cmdbase);
ret = pthread_join(tid_worker, NULL); ret = pthread_join(tid_worker, NULL);
if (ret != 0) if (ret != 0)
@ -280,9 +223,4 @@ worker_deinit(void)
// Free event base (should free events too) // Free event base (should free events too)
event_base_free(evbase_worker); event_base_free(evbase_worker);
// Close pipes and free command base
commands_base_free(cmdbase);
close(g_exit_pipe[0]);
close(g_exit_pipe[1]);
} }