Merge pull request #268 from chme/threadexit
Refactor thread exit handling
This commit is contained in:
commit
547783d008
65
src/cache.c
65
src/cache.c
|
@ -72,8 +72,6 @@ static pthread_t tid_cache;
|
|||
|
||||
// Event base, pipes and events
|
||||
struct event_base *evbase_cache;
|
||||
static int g_exit_pipe[2];
|
||||
static struct event *g_exitev;
|
||||
static struct event *g_cacheev;
|
||||
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 --------------------------------- */
|
||||
/* Thread: cache */
|
||||
|
||||
|
@ -1316,23 +1302,6 @@ cache(void *arg)
|
|||
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 --------------------------- */
|
||||
|
||||
|
@ -1637,17 +1606,6 @@ cache_init(void)
|
|||
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();
|
||||
if (!evbase_cache)
|
||||
{
|
||||
|
@ -1655,13 +1613,6 @@ cache_init(void)
|
|||
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);
|
||||
if (!g_cacheev)
|
||||
{
|
||||
|
@ -1669,9 +1620,7 @@ cache_init(void)
|
|||
goto evnew_fail;
|
||||
}
|
||||
|
||||
event_add(g_exitev, NULL);
|
||||
|
||||
cmdbase = commands_base_new(evbase_cache);
|
||||
cmdbase = commands_base_new(evbase_cache, NULL);
|
||||
|
||||
DPRINTF(E_INFO, L_CACHE, "cache thread init\n");
|
||||
|
||||
|
@ -1698,10 +1647,6 @@ cache_init(void)
|
|||
evbase_cache = NULL;
|
||||
|
||||
evbase_fail:
|
||||
close(g_exit_pipe[0]);
|
||||
close(g_exit_pipe[1]);
|
||||
|
||||
exit_fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1713,7 +1658,8 @@ cache_deinit(void)
|
|||
if (!g_initialized)
|
||||
return;
|
||||
|
||||
thread_exit();
|
||||
g_initialized = 0;
|
||||
commands_base_destroy(cmdbase);
|
||||
|
||||
ret = pthread_join(tid_cache, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -1724,9 +1670,4 @@ cache_deinit(void)
|
|||
|
||||
// Free event base (should free events too)
|
||||
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]);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ struct command
|
|||
|
||||
struct commands_base
|
||||
{
|
||||
struct event_base *evbase;
|
||||
command_exit_cb exit_cb;
|
||||
int command_pipe[2];
|
||||
struct event *command_event;
|
||||
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 *
|
||||
commands_base_new(struct event_base *evbase)
|
||||
commands_base_new(struct event_base *evbase, command_exit_cb exit_cb)
|
||||
{
|
||||
struct commands_base *cmdbase;
|
||||
int ret;
|
||||
|
@ -213,6 +218,9 @@ commands_base_new(struct event_base *evbase)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cmdbase->evbase = evbase;
|
||||
cmdbase->exit_cb = exit_cb;
|
||||
|
||||
return cmdbase;
|
||||
}
|
||||
|
||||
|
@ -359,3 +367,39 @@ commands_exec_async(struct commands_base *cmdbase, command_function func, void *
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,11 +39,14 @@ enum command_state {
|
|||
*/
|
||||
typedef enum command_state (*command_function)(void *arg, int *ret);
|
||||
|
||||
typedef void (*command_exit_cb)(void);
|
||||
|
||||
|
||||
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
|
||||
commands_base_free(struct commands_base *cmdbase);
|
||||
|
@ -60,5 +63,7 @@ commands_exec_sync(struct commands_base *cmdbase, command_function func, command
|
|||
int
|
||||
commands_exec_async(struct commands_base *cmdbase, command_function func, void *arg);
|
||||
|
||||
void
|
||||
commands_base_destroy(struct commands_base *cmdbase);
|
||||
|
||||
#endif /* SRC_COMMANDS_H_ */
|
||||
|
|
|
@ -104,12 +104,10 @@ struct stacked_dir {
|
|||
struct stacked_dir *next;
|
||||
};
|
||||
|
||||
static int exit_pipe[2];
|
||||
static int scan_exit;
|
||||
static int inofd;
|
||||
static struct event_base *evbase_scan;
|
||||
static struct event *inoev;
|
||||
static struct event *exitev;
|
||||
static pthread_t tid_scan;
|
||||
static struct deferred_pl *playlists;
|
||||
static struct stacked_dir *dirstack;
|
||||
|
@ -1911,13 +1909,6 @@ inofd_event_unset(void)
|
|||
}
|
||||
|
||||
/* Thread: scan */
|
||||
static void
|
||||
exit_cb(int fd, short event, void *arg)
|
||||
{
|
||||
event_base_loopbreak(evbase_scan);
|
||||
|
||||
scan_exit = 1;
|
||||
}
|
||||
|
||||
static enum command_state
|
||||
filescanner_initscan(void *arg, int *retval)
|
||||
|
@ -2002,32 +1993,13 @@ filescanner_init(void)
|
|||
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();
|
||||
if (ret < 0)
|
||||
{
|
||||
goto ino_fail;
|
||||
}
|
||||
|
||||
cmdbase = commands_base_new(evbase_scan);
|
||||
cmdbase = commands_base_new(evbase_scan, NULL);
|
||||
|
||||
ret = pthread_create(&tid_scan, NULL, filescanner, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -2048,11 +2020,7 @@ filescanner_init(void)
|
|||
thread_fail:
|
||||
commands_base_free(cmdbase);
|
||||
close(inofd);
|
||||
exitev_fail:
|
||||
ino_fail:
|
||||
close(exit_pipe[0]);
|
||||
close(exit_pipe[1]);
|
||||
pipe_fail:
|
||||
event_base_free(evbase_scan);
|
||||
|
||||
return -1;
|
||||
|
@ -2063,17 +2031,9 @@ void
|
|||
filescanner_deinit(void)
|
||||
{
|
||||
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;
|
||||
commands_base_destroy(cmdbase);
|
||||
|
||||
ret = pthread_join(tid_scan, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -2086,7 +2046,4 @@ filescanner_deinit(void)
|
|||
inofd_event_unset();
|
||||
|
||||
event_base_free(evbase_scan);
|
||||
commands_base_free(cmdbase);
|
||||
close(exit_pipe[0]);
|
||||
close(exit_pipe[1]);
|
||||
}
|
||||
|
|
62
src/mpd.c
62
src/mpd.c
|
@ -68,8 +68,6 @@
|
|||
static pthread_t tid_mpd;
|
||||
|
||||
static struct event_base *evbase_mpd;
|
||||
static int g_exit_pipe[2];
|
||||
static struct event *g_exitev;
|
||||
|
||||
static struct commands_base *cmdbase;
|
||||
|
||||
|
@ -192,17 +190,6 @@ struct idle_client
|
|||
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 */
|
||||
static void *
|
||||
|
@ -225,21 +212,6 @@ mpd(void *arg)
|
|||
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
|
||||
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");
|
||||
|
||||
#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();
|
||||
if (!evbase_mpd)
|
||||
{
|
||||
|
@ -4688,16 +4649,7 @@ int mpd_init(void)
|
|||
goto evbase_fail;
|
||||
}
|
||||
|
||||
g_exitev = event_new(evbase_mpd, g_exit_pipe[0], EV_READ, exit_cb, 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);
|
||||
cmdbase = commands_base_new(evbase_mpd, NULL);
|
||||
|
||||
if (v6enabled)
|
||||
{
|
||||
|
@ -4808,15 +4760,10 @@ int mpd_init(void)
|
|||
evconnlistener_free(listener);
|
||||
connew_fail:
|
||||
commands_base_free(cmdbase);
|
||||
evnew_fail:
|
||||
event_base_free(evbase_mpd);
|
||||
evbase_mpd = NULL;
|
||||
|
||||
evbase_fail:
|
||||
close(g_exit_pipe[0]);
|
||||
close(g_exit_pipe[1]);
|
||||
|
||||
exit_fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -4835,7 +4782,7 @@ void mpd_deinit(void)
|
|||
return;
|
||||
}
|
||||
|
||||
thread_exit();
|
||||
commands_base_destroy(cmdbase);
|
||||
|
||||
ret = pthread_join(tid_mpd, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -4861,9 +4808,4 @@ void mpd_deinit(void)
|
|||
|
||||
// Free event base (should free events too)
|
||||
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]);
|
||||
}
|
||||
|
|
51
src/player.c
51
src/player.c
|
@ -220,9 +220,7 @@ union player_arg
|
|||
|
||||
struct event_base *evbase_player;
|
||||
|
||||
static int exit_pipe[2];
|
||||
static int player_exit;
|
||||
static struct event *exitev;
|
||||
static pthread_t tid_player;
|
||||
static struct commands_base *cmdbase;
|
||||
|
||||
|
@ -3952,14 +3950,6 @@ player(void *arg)
|
|||
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 */
|
||||
int
|
||||
|
@ -4041,18 +4031,6 @@ player_init(void)
|
|||
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();
|
||||
if (!evbase_player)
|
||||
{
|
||||
|
@ -4061,13 +4039,6 @@ player_init(void)
|
|||
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__)
|
||||
pb_timer_ev = event_new(evbase_player, pb_timer_fd, EV_READ | EV_PERSIST, player_playback_cb, NULL);
|
||||
#else
|
||||
|
@ -4079,10 +4050,9 @@ player_init(void)
|
|||
goto evnew_fail;
|
||||
}
|
||||
|
||||
event_add(exitev, NULL);
|
||||
event_add(pb_timer_ev, NULL);
|
||||
|
||||
cmdbase = commands_base_new(evbase_player);
|
||||
cmdbase = commands_base_new(evbase_player, NULL);
|
||||
|
||||
ret = outputs_init();
|
||||
if (ret < 0)
|
||||
|
@ -4112,9 +4082,6 @@ player_init(void)
|
|||
evnew_fail:
|
||||
event_base_free(evbase_player);
|
||||
evbase_fail:
|
||||
close(exit_pipe[0]);
|
||||
close(exit_pipe[1]);
|
||||
exit_fail:
|
||||
evbuffer_free(audio_buf);
|
||||
audio_fail:
|
||||
#if defined(__linux__)
|
||||
|
@ -4131,20 +4098,14 @@ void
|
|||
player_deinit(void)
|
||||
{
|
||||
int ret;
|
||||
int dummy = 42;
|
||||
|
||||
ret = write(exit_pipe[1], &dummy, sizeof(dummy));
|
||||
if (ret != sizeof(dummy))
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Could not write to exit pipe: %s\n", strerror(errno));
|
||||
|
||||
return;
|
||||
}
|
||||
player_exit = 1;
|
||||
commands_base_destroy(cmdbase);
|
||||
|
||||
ret = pthread_join(tid_player, NULL);
|
||||
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;
|
||||
}
|
||||
|
@ -4164,8 +4125,4 @@ player_deinit(void)
|
|||
outputs_deinit();
|
||||
|
||||
event_base_free(evbase_player);
|
||||
|
||||
commands_base_free(cmdbase);
|
||||
close(exit_pipe[0]);
|
||||
close(exit_pipe[1]);
|
||||
}
|
||||
|
|
|
@ -114,9 +114,7 @@ static pthread_cond_t login_cond;
|
|||
|
||||
// Event base, pipes and events
|
||||
struct event_base *evbase_spotify;
|
||||
static int g_exit_pipe[2];
|
||||
static int g_notify_pipe[2];
|
||||
static struct event *g_exitev;
|
||||
static struct event *g_notifyev;
|
||||
|
||||
static struct commands_base *cmdbase;
|
||||
|
@ -384,21 +382,6 @@ fptr_assign_all()
|
|||
// 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 ------------------------- */
|
||||
/* Should only be called from within the spotify thread */
|
||||
|
||||
|
@ -1619,23 +1602,11 @@ spotify(void *arg)
|
|||
}
|
||||
|
||||
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_logout(g_sess);
|
||||
|
||||
event_base_loopbreak(evbase_spotify);
|
||||
|
||||
g_state = SPOTIFY_STATE_INACTIVE;
|
||||
|
||||
event_add(g_exitev, NULL);
|
||||
}
|
||||
|
||||
/* Process events when timeout expires or triggered by libspotify's notify_main_thread */
|
||||
|
@ -1976,17 +1947,6 @@ spotify_init(void)
|
|||
if (ret < 0)
|
||||
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
|
||||
ret = pipe2(g_notify_pipe, O_CLOEXEC);
|
||||
#else
|
||||
|
@ -2005,13 +1965,6 @@ spotify_init(void)
|
|||
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);
|
||||
if (!g_notifyev)
|
||||
{
|
||||
|
@ -2019,11 +1972,10 @@ spotify_init(void)
|
|||
goto evnew_fail;
|
||||
}
|
||||
|
||||
event_add(g_exitev, NULL);
|
||||
event_add(g_notifyev, NULL);
|
||||
|
||||
|
||||
cmdbase = commands_base_new(evbase_spotify);
|
||||
cmdbase = commands_base_new(evbase_spotify, exit_cb);
|
||||
if (!cmdbase)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not create command base\n");
|
||||
|
@ -2116,10 +2068,6 @@ spotify_init(void)
|
|||
close(g_notify_pipe[1]);
|
||||
|
||||
notify_fail:
|
||||
close(g_exit_pipe[0]);
|
||||
close(g_exit_pipe[1]);
|
||||
|
||||
exit_fail:
|
||||
assign_fail:
|
||||
dlclose(g_libhandle);
|
||||
g_libhandle = NULL;
|
||||
|
@ -2139,7 +2087,8 @@ spotify_deinit(void)
|
|||
/* Send exit signal to thread (if active) */
|
||||
if (g_state != SPOTIFY_STATE_INACTIVE)
|
||||
{
|
||||
thread_exit();
|
||||
commands_base_destroy(cmdbase);
|
||||
g_state = SPOTIFY_STATE_INACTIVE;
|
||||
|
||||
ret = pthread_join(tid_spotify, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -2155,12 +2104,9 @@ spotify_deinit(void)
|
|||
/* Free event base (should free events too) */
|
||||
event_base_free(evbase_spotify);
|
||||
|
||||
/* Close pipes and free command base */
|
||||
commands_base_free(cmdbase);
|
||||
/* Close pipes */
|
||||
close(g_notify_pipe[0]);
|
||||
close(g_notify_pipe[1]);
|
||||
close(g_exit_pipe[0]);
|
||||
close(g_exit_pipe[1]);
|
||||
|
||||
/* Destroy locks */
|
||||
pthread_cond_destroy(&login_cond);
|
||||
|
|
68
src/worker.c
68
src/worker.c
|
@ -58,8 +58,6 @@ static pthread_t tid_worker;
|
|||
// Event base, pipes and events
|
||||
struct event_base *evbase_worker;
|
||||
static int g_initialized;
|
||||
static int g_exit_pipe[2];
|
||||
static struct event *g_exitev;
|
||||
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 --------------------------------- */
|
||||
/* Thread: worker */
|
||||
|
||||
|
@ -146,23 +130,6 @@ worker(void *arg)
|
|||
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 --------------------------- */
|
||||
|
||||
|
@ -205,17 +172,6 @@ worker_init(void)
|
|||
{
|
||||
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();
|
||||
if (!evbase_worker)
|
||||
{
|
||||
|
@ -223,16 +179,7 @@ worker_init(void)
|
|||
goto evbase_fail;
|
||||
}
|
||||
|
||||
g_exitev = event_new(evbase_worker, g_exit_pipe[0], EV_READ, exit_cb, 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);
|
||||
cmdbase = commands_base_new(evbase_worker, NULL);
|
||||
|
||||
ret = pthread_create(&tid_worker, NULL, worker, NULL);
|
||||
if (ret < 0)
|
||||
|
@ -252,15 +199,10 @@ worker_init(void)
|
|||
|
||||
thread_fail:
|
||||
commands_base_free(cmdbase);
|
||||
evnew_fail:
|
||||
event_base_free(evbase_worker);
|
||||
evbase_worker = NULL;
|
||||
|
||||
evbase_fail:
|
||||
close(g_exit_pipe[0]);
|
||||
close(g_exit_pipe[1]);
|
||||
|
||||
exit_fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -269,7 +211,8 @@ worker_deinit(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
thread_exit();
|
||||
g_initialized = 0;
|
||||
commands_base_destroy(cmdbase);
|
||||
|
||||
ret = pthread_join(tid_worker, NULL);
|
||||
if (ret != 0)
|
||||
|
@ -280,9 +223,4 @@ worker_deinit(void)
|
|||
|
||||
// Free event base (should free events too)
|
||||
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]);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue