mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-26 14:13:18 -05:00
[threads] Update mutex/cond functions to use new CHECK_ERR macros
Added various macros to check return values and log any errors and abort if the call fails. Updated logging to handle early errors before logging initialized.
This commit is contained in:
parent
b54d94fda6
commit
8e3797ec43
@ -78,7 +78,7 @@ command_cb_sync(struct commands_base *cmdbase, struct command *cmd)
|
||||
{
|
||||
enum command_state cmdstate;
|
||||
|
||||
fork_mutex_lock(&cmd->lck);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_lock(&cmd->lck));
|
||||
|
||||
cmdstate = cmd->func(cmd->arg, &cmd->ret);
|
||||
if (cmdstate == COMMAND_PENDING)
|
||||
@ -94,8 +94,8 @@ command_cb_sync(struct commands_base *cmdbase, struct command *cmd)
|
||||
cmd->func_bh(cmd->arg, &cmd->ret);
|
||||
|
||||
// Signal the calling thread that the command execution finished
|
||||
fork_cond_signal(&cmd->cond);
|
||||
fork_mutex_unlock(&cmd->lck);
|
||||
CHECK_ERR(L_MAIN, pthread_cond_signal(&cmd->cond));
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_unlock(&cmd->lck));
|
||||
|
||||
event_add(cmdbase->command_event, NULL);
|
||||
}
|
||||
@ -283,8 +283,8 @@ commands_exec_end(struct commands_base *cmdbase, int retvalue)
|
||||
{
|
||||
cmdbase->current_cmd->func_bh(cmdbase->current_cmd->arg, &cmdbase->current_cmd->ret);
|
||||
}
|
||||
fork_cond_signal(&cmdbase->current_cmd->cond);
|
||||
fork_mutex_unlock(&cmdbase->current_cmd->lck);
|
||||
CHECK_ERR(L_MAIN, pthread_cond_signal(&cmdbase->current_cmd->cond));
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_unlock(&cmdbase->current_cmd->lck));
|
||||
|
||||
cmdbase->current_cmd = NULL;
|
||||
|
||||
@ -317,10 +317,10 @@ commands_exec_sync(struct commands_base *cmdbase, command_function func, command
|
||||
cmd.arg = arg;
|
||||
cmd.nonblock = 0;
|
||||
|
||||
fork_mutex_init(&cmd.lck);
|
||||
fork_cond_init(&cmd.cond);
|
||||
CHECK_ERR(L_MAIN, mutex_init(&cmd.lck));
|
||||
CHECK_ERR(L_MAIN, pthread_cond_init(&cmd.cond, NULL));
|
||||
|
||||
fork_mutex_lock(&cmd.lck);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_lock(&cmd.lck));
|
||||
|
||||
ret = send_command(cmdbase, &cmd);
|
||||
if (ret < 0)
|
||||
@ -330,12 +330,12 @@ commands_exec_sync(struct commands_base *cmdbase, command_function func, command
|
||||
}
|
||||
else
|
||||
{
|
||||
fork_cond_wait(&cmd.cond, &cmd.lck);
|
||||
CHECK_ERR(L_MAIN, pthread_cond_wait(&cmd.cond, &cmd.lck));
|
||||
}
|
||||
fork_mutex_unlock(&cmd.lck);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_unlock(&cmd.lck));
|
||||
|
||||
fork_cond_destroy(&cmd.cond);
|
||||
fork_mutex_destroy(&cmd.lck);
|
||||
CHECK_ERR(L_MAIN, pthread_cond_destroy(&cmd.cond));
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_destroy(&cmd.lck));
|
||||
|
||||
return cmd.ret;
|
||||
}
|
||||
|
20
src/db.c
20
src/db.c
@ -530,12 +530,12 @@ unlock_notify_cb(void **args, int nargs)
|
||||
{
|
||||
u = (struct db_unlock *)args[i];
|
||||
|
||||
fork_mutex_lock(&u->lck);
|
||||
CHECK_ERR(L_DB, pthread_mutex_lock(&u->lck));
|
||||
|
||||
u->proceed = 1;
|
||||
fork_cond_signal(&u->cond);
|
||||
CHECK_ERR(L_DB, pthread_cond_signal(&u->cond));
|
||||
|
||||
fork_mutex_unlock(&u->lck);
|
||||
CHECK_ERR(L_DB, pthread_mutex_unlock(&u->lck));
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,25 +546,25 @@ db_wait_unlock(void)
|
||||
int ret;
|
||||
|
||||
u.proceed = 0;
|
||||
fork_mutex_init(&u.lck);
|
||||
fork_cond_init(&u.cond);
|
||||
CHECK_ERR(L_DB, mutex_init(&u.lck));
|
||||
CHECK_ERR(L_DB, pthread_cond_init(&u.cond, NULL));
|
||||
|
||||
ret = sqlite3_unlock_notify(hdl, unlock_notify_cb, &u);
|
||||
if (ret == SQLITE_OK)
|
||||
{
|
||||
fork_mutex_lock(&u.lck);
|
||||
CHECK_ERR(L_DB, pthread_mutex_lock(&u.lck));
|
||||
|
||||
if (!u.proceed)
|
||||
{
|
||||
DPRINTF(E_INFO, L_DB, "Waiting for database unlock\n");
|
||||
fork_cond_wait(&u.cond, &u.lck);
|
||||
CHECK_ERR(L_DB, pthread_cond_wait(&u.cond, &u.lck));
|
||||
}
|
||||
|
||||
fork_mutex_unlock(&u.lck);
|
||||
CHECK_ERR(L_DB, pthread_mutex_unlock(&u.lck));
|
||||
}
|
||||
|
||||
fork_cond_destroy(&u.cond);
|
||||
fork_mutex_destroy(&u.lck);
|
||||
CHECK_ERR(L_DB, pthread_cond_destroy(&u.cond));
|
||||
CHECK_ERR(L_DB, pthread_mutex_destroy(&u.lck));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
84
src/logger.c
84
src/logger.c
@ -37,15 +37,23 @@
|
||||
#include "conffile.h"
|
||||
#include "misc.h"
|
||||
|
||||
static pthread_mutex_t logger_lck = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t logger_lck;
|
||||
static int logger_initialized;
|
||||
static int logdomains;
|
||||
static int threshold;
|
||||
static int console;
|
||||
static int console = 1;
|
||||
static char *logfilename;
|
||||
static FILE *logfile;
|
||||
static char *labels[] = { "config", "daap", "db", "httpd", "http", "main", "mdns", "misc", "rsp", "scan", "xcode", "event", "remote", "dacp", "ffmpeg", "artwork", "player", "raop", "laudio", "dmap", "dbperf", "spotify", "lastfm", "cache", "mpd", "stream", "cast", "fifo" };
|
||||
static char *severities[] = { "FATAL", "LOG", "WARN", "INFO", "DEBUG", "SPAM" };
|
||||
|
||||
/* We need our own check to avoid nested locking or recursive calls */
|
||||
#define LOGGER_CHECK_ERR(f) \
|
||||
do { int lerr; lerr = f; if (lerr != 0) { \
|
||||
vlogger_fatal("%s failed at line %d, err %d (%s)\n", #f, __LINE__, \
|
||||
lerr, strerror(lerr)); \
|
||||
abort(); \
|
||||
} } while(0)
|
||||
|
||||
static int
|
||||
set_logdomains(char *domains)
|
||||
@ -80,24 +88,13 @@ set_logdomains(char *domains)
|
||||
}
|
||||
|
||||
static void
|
||||
vlogger(int severity, int domain, const char *fmt, va_list args)
|
||||
vlogger_writer(int severity, int domain, const char *fmt, va_list args)
|
||||
{
|
||||
va_list ap;
|
||||
char stamp[32];
|
||||
time_t t;
|
||||
int ret;
|
||||
|
||||
if (!((1 << domain) & logdomains) || (severity > threshold))
|
||||
return;
|
||||
|
||||
fork_mutex_lock(&logger_lck);
|
||||
|
||||
if (!logfile && !console)
|
||||
{
|
||||
fork_mutex_unlock(&logger_lck);
|
||||
return;
|
||||
}
|
||||
|
||||
if (logfile)
|
||||
{
|
||||
t = time(NULL);
|
||||
@ -122,8 +119,43 @@ vlogger(int severity, int domain, const char *fmt, va_list args)
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
fork_mutex_unlock(&logger_lck);
|
||||
static void
|
||||
vlogger_fatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vlogger_writer(E_FATAL, L_MISC, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void
|
||||
vlogger(int severity, int domain, const char *fmt, va_list args)
|
||||
{
|
||||
|
||||
if(! logger_initialized)
|
||||
{
|
||||
/* lock not initialized, use stderr */
|
||||
vlogger_writer(severity, domain, fmt, args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!((1 << domain) & logdomains) || (severity > threshold))
|
||||
return;
|
||||
|
||||
LOGGER_CHECK_ERR(pthread_mutex_lock(&logger_lck));
|
||||
|
||||
if (!logfile && !console)
|
||||
{
|
||||
LOGGER_CHECK_ERR(pthread_mutex_unlock(&logger_lck));
|
||||
return;
|
||||
}
|
||||
|
||||
vlogger_writer(severity, domain, fmt, args);
|
||||
|
||||
LOGGER_CHECK_ERR(pthread_mutex_unlock(&logger_lck));
|
||||
}
|
||||
|
||||
void
|
||||
@ -204,7 +236,7 @@ logger_reinit(void)
|
||||
if (!logfile)
|
||||
return;
|
||||
|
||||
fork_mutex_lock(&logger_lck);
|
||||
LOGGER_CHECK_ERR(pthread_mutex_lock(&logger_lck));
|
||||
|
||||
fp = fopen(logfilename, "a");
|
||||
if (!fp)
|
||||
@ -218,7 +250,7 @@ logger_reinit(void)
|
||||
logfile = fp;
|
||||
|
||||
out:
|
||||
fork_mutex_unlock(&logger_lck);
|
||||
LOGGER_CHECK_ERR(pthread_mutex_unlock(&logger_lck));
|
||||
}
|
||||
|
||||
|
||||
@ -287,6 +319,11 @@ logger_init(char *file, char *domains, int severity)
|
||||
|
||||
logfilename = file;
|
||||
|
||||
/* logging w/o locks before initialized complete */
|
||||
CHECK_ERR(L_MISC, mutex_init(&logger_lck));
|
||||
|
||||
logger_initialized = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -294,5 +331,16 @@ void
|
||||
logger_deinit(void)
|
||||
{
|
||||
if (logfile)
|
||||
fclose(logfile);
|
||||
{
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
}
|
||||
|
||||
if(logger_initialized)
|
||||
{
|
||||
/* logging w/o locks to stderr now */
|
||||
logger_initialized = 0;
|
||||
console = 1;
|
||||
CHECK_ERR(L_MISC, pthread_mutex_destroy(&logger_lck));
|
||||
}
|
||||
}
|
||||
|
@ -428,19 +428,19 @@ ffmpeg_lockmgr(void **pmutex, enum AVLockOp op)
|
||||
*pmutex = malloc(sizeof(pthread_mutex_t));
|
||||
if (!*pmutex)
|
||||
return 1;
|
||||
fork_mutex_init(*pmutex);
|
||||
CHECK_ERR(L_MAIN, mutex_init(*pmutex));
|
||||
return 0;
|
||||
|
||||
case AV_LOCK_OBTAIN:
|
||||
fork_mutex_lock(*pmutex);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_lock(*pmutex));
|
||||
return 0;
|
||||
|
||||
case AV_LOCK_RELEASE:
|
||||
fork_mutex_unlock(*pmutex);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_unlock(*pmutex));
|
||||
return 0;
|
||||
|
||||
case AV_LOCK_DESTROY:
|
||||
fork_mutex_destroy(*pmutex);
|
||||
CHECK_ERR(L_MAIN, pthread_mutex_destroy(*pmutex));
|
||||
free(*pmutex);
|
||||
*pmutex = NULL;
|
||||
|
||||
@ -450,7 +450,6 @@ ffmpeg_lockmgr(void **pmutex, enum AVLockOp op)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
91
src/misc.c
91
src/misc.c
@ -920,87 +920,34 @@ timespec_cmp(struct timespec time1, struct timespec time2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fork_mutex_init(pthread_mutex_t *mutex)
|
||||
int
|
||||
mutex_init(pthread_mutex_t *mutex)
|
||||
{
|
||||
pthread_mutexattr_t mattr;
|
||||
int err;
|
||||
|
||||
err = pthread_mutexattr_init(&mattr);
|
||||
assert(err == 0);
|
||||
err = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
assert(err == 0);
|
||||
CHECK_ERR(L_MISC, pthread_mutexattr_init(&mattr));
|
||||
CHECK_ERR(L_MISC, pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK));
|
||||
err = pthread_mutex_init(mutex, &mattr);
|
||||
assert(err == 0);
|
||||
err = pthread_mutexattr_destroy(&mattr);
|
||||
assert(err == 0);
|
||||
}
|
||||
CHECK_ERR(L_MISC, pthread_mutexattr_destroy(&mattr));
|
||||
|
||||
void
|
||||
fork_mutex_lock(pthread_mutex_t *mutex)
|
||||
{
|
||||
int err;
|
||||
err = pthread_mutex_lock(mutex);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
void
|
||||
fork_mutex_unlock(pthread_mutex_t *mutex)
|
||||
{
|
||||
int err;
|
||||
err = pthread_mutex_unlock(mutex);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
void
|
||||
fork_mutex_destroy(pthread_mutex_t *mutex)
|
||||
{
|
||||
int err;
|
||||
err = pthread_mutex_destroy(mutex);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
/* condition wrappers with checks */
|
||||
void
|
||||
fork_cond_init(pthread_cond_t *cond)
|
||||
{
|
||||
int err;
|
||||
err = pthread_cond_init(cond, NULL);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
void
|
||||
fork_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
int err;
|
||||
err = pthread_cond_wait(cond, mutex);
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
int
|
||||
fork_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *ts)
|
||||
{
|
||||
int err;
|
||||
err = pthread_cond_timedwait(cond, mutex, ts);
|
||||
if(err == ETIMEDOUT)
|
||||
return err;
|
||||
assert(err == 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
fork_cond_signal(pthread_cond_t *cond)
|
||||
{
|
||||
int err;
|
||||
err = pthread_cond_signal(cond);
|
||||
assert(err == 0);
|
||||
void log_fatal_err(int domain, const char *func, int line, int err) {
|
||||
DPRINTF(E_FATAL, domain, "%s failed at line %d, error %d (%s)\n", func,
|
||||
line, err, strerror(err));
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
fork_cond_destroy(pthread_cond_t *cond)
|
||||
{
|
||||
int err;
|
||||
err = pthread_cond_destroy(cond);
|
||||
assert(err == 0);
|
||||
void log_fatal_errno(int domain, const char *func, int line) {
|
||||
DPRINTF(E_FATAL, domain, "%s failed at line %d, error %d (%s)\n", func,
|
||||
line, errno, strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
void log_fatal_null(int domain, const char *func, int line) {
|
||||
DPRINTF(E_FATAL, domain, "%s returned NULL at line %d\n", func, line);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
64
src/misc.h
64
src/misc.h
@ -97,27 +97,49 @@ timespec_add(struct timespec time1, struct timespec time2);
|
||||
int
|
||||
timespec_cmp(struct timespec time1, struct timespec time2);
|
||||
|
||||
/* mutex wrappers with checks */
|
||||
void
|
||||
fork_mutex_init(pthread_mutex_t *mutex);
|
||||
void
|
||||
fork_mutex_lock(pthread_mutex_t *mutex);
|
||||
void
|
||||
fork_mutex_unlock(pthread_mutex_t *mutex);
|
||||
void
|
||||
fork_mutex_destroy(pthread_mutex_t *mutex);
|
||||
|
||||
/* condition wrappers with checks */
|
||||
void
|
||||
fork_cond_init(pthread_cond_t *cond);
|
||||
void
|
||||
fork_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
||||
/* initialize mutex with error checking (not default on all platforms) */
|
||||
int
|
||||
fork_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *ts);
|
||||
void
|
||||
fork_cond_signal(pthread_cond_t *cond);
|
||||
void
|
||||
fork_cond_destroy(pthread_cond_t *cond);
|
||||
mutex_init(pthread_mutex_t *mutex);
|
||||
|
||||
/* Check that the function returns 0, logging a fatal error referencing
|
||||
returned error (type errno) if it fails, and aborts the process.
|
||||
Example: CHECK_ERR(L_MAIN, my_function()); */
|
||||
#define CHECK_ERR(d, f) \
|
||||
do { int chk_err; \
|
||||
if ( (chk_err = (f)) != 0) \
|
||||
log_fatal_err(d, #f, __LINE__, chk_err); \
|
||||
} while(0)
|
||||
|
||||
/* Check that the function returns 0 or okval, logging a fatal
|
||||
error referencing returned erro (type errno) if not, and aborts the process.
|
||||
Example: int err; CHECK_ERR_EXCEPT(L_MAIN, my_wait(), err, ETIMEDOUT); */
|
||||
#define CHECK_ERR_EXCEPT(d, f, var, okval) \
|
||||
do { (var) = (f); \
|
||||
if (! (((var) == (okval)) || ((var) == 0))) \
|
||||
log_fatal_err(d, #f, __LINE__, (var)); \
|
||||
} while(0)
|
||||
|
||||
/* Check that the function returns value >= 0, logging a fatal error
|
||||
referencing errno if it not, and aborts the process.
|
||||
Example: int ret; CHECK_ERRNO(L_MAIN, ret = my_function()); */
|
||||
#define CHECK_ERRNO(d, f) \
|
||||
do { \
|
||||
if ( (f) < 0 ) \
|
||||
log_fatal_errno(d, #f, __LINE__); \
|
||||
} while(0)
|
||||
|
||||
/* Check that the function returns non-NULL, logging a fatal error if not,
|
||||
and aborts the process.
|
||||
Example: void *ptr; CHECK_NULL(L_MAIN, ptr = my_create()); */
|
||||
#define CHECK_NULL(d, f) \
|
||||
do { \
|
||||
if ( (f) == NULL ) \
|
||||
log_fatal_null(d, #f, __LINE__); \
|
||||
} while(0)
|
||||
|
||||
/* Used by CHECK_*() macros */
|
||||
void log_fatal_err(int domain, const char *func, int line, int err);
|
||||
void log_fatal_errno(int domain, const char *func, int line);
|
||||
void log_fatal_null(int domain, const char *func, int line);
|
||||
|
||||
#endif /* !__MISC_H__ */
|
||||
|
@ -84,7 +84,7 @@ static int pairing_efd;
|
||||
static int pairing_pipe[2];
|
||||
#endif
|
||||
static struct event *pairingev;
|
||||
static pthread_mutex_t remote_lck = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t remote_lck;
|
||||
static struct remote_info *remote_list;
|
||||
|
||||
|
||||
@ -660,7 +660,7 @@ pairing_cb(int fd, short event, void *arg)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
fork_mutex_lock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_lock(&remote_lck));
|
||||
|
||||
for (ri = remote_list; ri; ri = ri->next)
|
||||
{
|
||||
@ -672,7 +672,7 @@ pairing_cb(int fd, short event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
fork_mutex_unlock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&remote_lck));
|
||||
|
||||
if (!ri)
|
||||
break;
|
||||
@ -699,11 +699,11 @@ touch_remote_cb(const char *name, const char *type, const char *domain, const ch
|
||||
* failed; any subsequent attempt will need a new pairing pin, so
|
||||
* we can just forget everything we know about the remote.
|
||||
*/
|
||||
fork_mutex_lock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_lock(&remote_lck));
|
||||
|
||||
remove_remote_address_byid(name, family);
|
||||
|
||||
fork_mutex_unlock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&remote_lck));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -761,7 +761,7 @@ touch_remote_cb(const char *name, const char *type, const char *domain, const ch
|
||||
DPRINTF(E_LOG, L_REMOTE, "Discovered remote '%s' (id %s) at %s:%d, paircode %s\n", devname, name, address, port, paircode);
|
||||
|
||||
/* Add the data to the list, adding the remote to the list if needed */
|
||||
fork_mutex_lock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_lock(&remote_lck));
|
||||
|
||||
ret = add_remote_mdns_data(name, family, address, port, devname, paircode);
|
||||
|
||||
@ -775,7 +775,7 @@ touch_remote_cb(const char *name, const char *type, const char *domain, const ch
|
||||
else if (ret == 1)
|
||||
kickoff_pairing();
|
||||
|
||||
fork_mutex_unlock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&remote_lck));
|
||||
}
|
||||
}
|
||||
|
||||
@ -885,7 +885,7 @@ remote_pairing_read_pin(char *path)
|
||||
|
||||
DPRINTF(E_LOG, L_REMOTE, "Read Remote pairing data (name '%s', pin '%s') from %s\n", devname, pin, path);
|
||||
|
||||
fork_mutex_lock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_lock(&remote_lck));
|
||||
|
||||
ret = add_remote_pin_data(devname, pin);
|
||||
free(devname);
|
||||
@ -894,7 +894,7 @@ remote_pairing_read_pin(char *path)
|
||||
else
|
||||
kickoff_pairing();
|
||||
|
||||
fork_mutex_unlock(&remote_lck);
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_unlock(&remote_lck));
|
||||
}
|
||||
|
||||
|
||||
@ -906,6 +906,8 @@ remote_pairing_init(void)
|
||||
|
||||
remote_list = NULL;
|
||||
|
||||
CHECK_ERR(L_REMOTE, mutex_init(&remote_lck));
|
||||
|
||||
#ifdef HAVE_EVENTFD
|
||||
pairing_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
if (pairing_efd < 0)
|
||||
@ -989,4 +991,6 @@ remote_pairing_deinit(void)
|
||||
close(pairing_pipe[0]);
|
||||
close(pairing_pipe[1]);
|
||||
#endif
|
||||
|
||||
CHECK_ERR(L_REMOTE, pthread_mutex_destroy(&remote_lck));
|
||||
}
|
||||
|
@ -1489,7 +1489,7 @@ audio_fifo_flush(void)
|
||||
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Flushing audio fifo\n");
|
||||
|
||||
fork_mutex_lock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&g_audio_fifo->mutex));
|
||||
|
||||
while((afd = TAILQ_FIRST(&g_audio_fifo->q))) {
|
||||
TAILQ_REMOVE(&g_audio_fifo->q, afd, link);
|
||||
@ -1498,7 +1498,7 @@ audio_fifo_flush(void)
|
||||
|
||||
g_audio_fifo->qlen = 0;
|
||||
g_audio_fifo->fullcount = 0;
|
||||
fork_mutex_unlock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&g_audio_fifo->mutex));
|
||||
}
|
||||
|
||||
static enum command_state
|
||||
@ -1668,6 +1668,7 @@ audio_get(void *arg, int *retval)
|
||||
int processed;
|
||||
int timeout;
|
||||
int ret;
|
||||
int err;
|
||||
int s;
|
||||
|
||||
audio = (struct audio_get_param *) arg;
|
||||
@ -1678,7 +1679,7 @@ audio_get(void *arg, int *retval)
|
||||
if (g_state == SPOTIFY_STATE_PAUSED)
|
||||
playback_play(NULL, retval);
|
||||
|
||||
fork_mutex_lock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&g_audio_fifo->mutex));
|
||||
|
||||
while ((processed < audio->wanted) && (g_state != SPOTIFY_STATE_STOPPED))
|
||||
{
|
||||
@ -1701,7 +1702,7 @@ audio_get(void *arg, int *retval)
|
||||
DPRINTF(E_DBG, L_SPOTIFY, "Waiting for audio\n");
|
||||
timeout += 5;
|
||||
mk_reltime(&ts, 5);
|
||||
fork_cond_timedwait(&g_audio_fifo->cond, &g_audio_fifo->mutex, &ts);
|
||||
CHECK_ERR_EXCEPT(L_SPOTIFY, pthread_cond_timedwait(&g_audio_fifo->cond, &g_audio_fifo->mutex, &ts), err, ETIMEDOUT);
|
||||
}
|
||||
|
||||
if ((!afd) && (timeout >= SPOTIFY_TIMEOUT))
|
||||
@ -1725,7 +1726,7 @@ audio_get(void *arg, int *retval)
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Out of memory for evbuffer (tried to add %d bytes)\n", s);
|
||||
fork_mutex_unlock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&g_audio_fifo->mutex));
|
||||
*retval = -1;
|
||||
return COMMAND_END;
|
||||
}
|
||||
@ -1733,7 +1734,7 @@ audio_get(void *arg, int *retval)
|
||||
processed += s;
|
||||
}
|
||||
|
||||
fork_mutex_unlock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&g_audio_fifo->mutex));
|
||||
|
||||
|
||||
*retval = processed;
|
||||
@ -1747,12 +1748,12 @@ artwork_loaded_cb(sp_image *image, void *userdata)
|
||||
|
||||
artwork = userdata;
|
||||
|
||||
fork_mutex_lock(&artwork->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&artwork->mutex));
|
||||
|
||||
artwork->is_loaded = 1;
|
||||
|
||||
fork_cond_signal(&artwork->cond);
|
||||
fork_mutex_unlock(&artwork->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&artwork->cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&artwork->mutex));
|
||||
}
|
||||
|
||||
static enum command_state
|
||||
@ -1989,10 +1990,10 @@ logged_out(sp_session *sess)
|
||||
{
|
||||
DPRINTF(E_INFO, L_SPOTIFY, "Logout complete\n");
|
||||
|
||||
fork_mutex_lock(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&login_lck));
|
||||
|
||||
fork_cond_signal(&login_cond);
|
||||
fork_mutex_unlock(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&login_cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&login_lck));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2017,7 +2018,7 @@ static int music_delivery(sp_session *sess, const sp_audioformat *format,
|
||||
if (num_frames == 0)
|
||||
return 0; // Audio discontinuity, do nothing
|
||||
|
||||
fork_mutex_lock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&g_audio_fifo->mutex));
|
||||
|
||||
/* Buffer three seconds of audio */
|
||||
if (g_audio_fifo->qlen > (3 * format->sample_rate))
|
||||
@ -2033,7 +2034,7 @@ static int music_delivery(sp_session *sess, const sp_audioformat *format,
|
||||
g_audio_fifo->fullcount = 0;
|
||||
}
|
||||
|
||||
fork_mutex_unlock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&g_audio_fifo->mutex));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2050,8 +2051,8 @@ static int music_delivery(sp_session *sess, const sp_audioformat *format,
|
||||
TAILQ_INSERT_TAIL(&g_audio_fifo->q, afd, link);
|
||||
g_audio_fifo->qlen += num_frames;
|
||||
|
||||
fork_cond_signal(&g_audio_fifo->cond);
|
||||
fork_mutex_unlock(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_signal(&g_audio_fifo->cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&g_audio_fifo->mutex));
|
||||
|
||||
return num_frames;
|
||||
}
|
||||
@ -2365,25 +2366,26 @@ spotify_artwork_get(struct evbuffer *evbuf, char *path, int max_w, int max_h)
|
||||
struct artwork_get_param artwork;
|
||||
struct timespec ts;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
artwork.evbuf = evbuf;
|
||||
artwork.path = path;
|
||||
artwork.max_w = max_w;
|
||||
artwork.max_h = max_h;
|
||||
|
||||
fork_mutex_init(&artwork.mutex);
|
||||
fork_cond_init(&artwork.cond);
|
||||
CHECK_ERR(L_SPOTIFY, mutex_init(&artwork.mutex));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_init(&artwork.cond, NULL));
|
||||
|
||||
ret = commands_exec_sync(cmdbase, artwork_get, NULL, &artwork);
|
||||
|
||||
// Artwork was not ready, wait for callback from libspotify
|
||||
if (ret == 0)
|
||||
{
|
||||
fork_mutex_lock(&artwork.mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&artwork.mutex));
|
||||
mk_reltime(&ts, SPOTIFY_ARTWORK_TIMEOUT);
|
||||
if (!artwork.is_loaded)
|
||||
fork_cond_timedwait(&artwork.cond, &artwork.mutex, &ts);
|
||||
fork_mutex_unlock(&artwork.mutex);
|
||||
CHECK_ERR_EXCEPT(L_SPOTIFY, pthread_cond_timedwait(&artwork.cond, &artwork.mutex, &ts), err, ETIMEDOUT);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&artwork.mutex));
|
||||
|
||||
ret = commands_exec_sync(cmdbase, artwork_get_bh, NULL, &artwork);
|
||||
}
|
||||
@ -2431,7 +2433,7 @@ void
|
||||
spotify_oauth_callback(struct evbuffer *evbuf, struct evkeyvalq *param, const char *redirect_uri)
|
||||
{
|
||||
const char *code;
|
||||
const char *err;
|
||||
const char *err = "";
|
||||
int total;
|
||||
int ret;
|
||||
|
||||
@ -2499,7 +2501,7 @@ spotify_login(char *path)
|
||||
|
||||
if (SP_CONNECTION_STATE_LOGGED_IN == fptr_sp_session_connectionstate(g_sess))
|
||||
{
|
||||
fork_mutex_lock(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_lock(&login_lck));
|
||||
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Logging out of Spotify (current state is %d)\n", g_state);
|
||||
|
||||
@ -2509,12 +2511,12 @@ spotify_login(char *path)
|
||||
if (SP_ERROR_OK != err)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SPOTIFY, "Could not logout of Spotify: %s\n", fptr_sp_error_message(err));
|
||||
fork_mutex_unlock(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&login_lck));
|
||||
return;
|
||||
}
|
||||
|
||||
fork_cond_wait(&login_cond, &login_lck);
|
||||
fork_mutex_unlock(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_wait(&login_cond, &login_lck));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_unlock(&login_lck));
|
||||
}
|
||||
|
||||
DPRINTF(E_INFO, L_SPOTIFY, "Logging into Spotify\n");
|
||||
@ -2649,11 +2651,11 @@ spotify_init(void)
|
||||
}
|
||||
TAILQ_INIT(&g_audio_fifo->q);
|
||||
g_audio_fifo->qlen = 0;
|
||||
fork_mutex_init(&g_audio_fifo->mutex);
|
||||
fork_cond_init(&g_audio_fifo->cond);
|
||||
CHECK_ERR(L_SPOTIFY, mutex_init(&g_audio_fifo->mutex));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_init(&g_audio_fifo->cond, NULL));
|
||||
|
||||
fork_mutex_init(&login_lck);
|
||||
fork_cond_init(&login_cond);
|
||||
CHECK_ERR(L_SPOTIFY, mutex_init(&login_lck));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_init(&login_cond, NULL));
|
||||
|
||||
/* Spawn thread */
|
||||
ret = pthread_create(&tid_spotify, NULL, spotify, NULL);
|
||||
@ -2673,11 +2675,11 @@ spotify_init(void)
|
||||
return 0;
|
||||
|
||||
thread_fail:
|
||||
fork_cond_destroy(&login_cond);
|
||||
fork_mutex_destroy(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_destroy(&login_cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_destroy(&login_lck));
|
||||
|
||||
fork_cond_destroy(&g_audio_fifo->cond);
|
||||
fork_mutex_destroy(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_destroy(&g_audio_fifo->cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_destroy(&g_audio_fifo->mutex));
|
||||
free(g_audio_fifo);
|
||||
|
||||
audio_fifo_fail:
|
||||
@ -2737,12 +2739,12 @@ spotify_deinit(void)
|
||||
close(g_notify_pipe[1]);
|
||||
|
||||
/* Destroy locks */
|
||||
fork_cond_destroy(&login_cond);
|
||||
fork_mutex_destroy(&login_lck);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_destroy(&login_cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_destroy(&login_lck));
|
||||
|
||||
/* Clear audio fifo */
|
||||
fork_cond_destroy(&g_audio_fifo->cond);
|
||||
fork_mutex_destroy(&g_audio_fifo->mutex);
|
||||
CHECK_ERR(L_SPOTIFY, pthread_cond_destroy(&g_audio_fifo->cond));
|
||||
CHECK_ERR(L_SPOTIFY, pthread_mutex_destroy(&g_audio_fifo->mutex));
|
||||
free(g_audio_fifo);
|
||||
|
||||
/* Release libspotify handle */
|
||||
|
Loading…
x
Reference in New Issue
Block a user