From 79900f84e13976245807718a27a82c6f585ba76f Mon Sep 17 00:00:00 2001 From: jcorporation Date: Fri, 25 Jan 2019 01:08:38 +0100 Subject: [PATCH] Fix: valgrind memory still reachable errors in read_statefiles Fix: thread termination of mympd_api_thread --- src/global.c | 49 ----------- src/global.h.in | 32 ++++---- src/main.c | 175 +++++++++++++++++++++++---------------- src/mpd_client.c | 8 +- src/mympd_api.c | 207 ++++++++++++++++++++++++++--------------------- src/tiny_queue.c | 33 +++++--- 6 files changed, 262 insertions(+), 242 deletions(-) diff --git a/src/global.c b/src/global.c index dd98a0e..07c9f9c 100644 --- a/src/global.c +++ b/src/global.c @@ -33,55 +33,6 @@ #include "list.h" #include "global.h" -bool state_file_read(t_config *config, const char *name, char *value) { - char cfg_file[400]; - char *line = NULL; - size_t n = 0; - ssize_t read; - - if (!validate_string(name)) - return false; - snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); - FILE *fp = fopen(cfg_file, "r"); - if (fp == NULL) { - printf("Error opening %s\n", cfg_file); - return false; - } - read = getline(&line, &n, fp); - snprintf(value, 400, "%s", line); - LOG_DEBUG() fprintf(stderr, "DEBUG: State %s: %s\n", name, value); - fclose(fp); - free(line); - if (read > 0) - return true; - else - return false; -} - -bool state_file_write(t_config *config, const char *name, const char *value) { - char tmp_file[400]; - char cfg_file[400]; - - if (!validate_string(name)) - return false; - snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); - snprintf(tmp_file, 400, "%s/tmp/%s", config->varlibdir, name); - - FILE *fp = fopen(tmp_file, "w"); - if (fp == NULL) { - printf("Error opening %s\n", tmp_file); - return false; - } - fprintf(fp, "%s", value); - fclose(fp); - if (rename(tmp_file, cfg_file) == -1) { - printf("Error renaming file from %s to %s\n", tmp_file, cfg_file); - return false; - } - return true; -} - - bool testdir(const char *name, const char *dirname) { DIR* dir = opendir(dirname); if (dir) { diff --git a/src/global.h.in b/src/global.h.in index 330aa4b..7e43dce 100644 --- a/src/global.h.in +++ b/src/global.h.in @@ -158,33 +158,33 @@ typedef struct t_work_result { //myMPD configuration typedef struct t_config { long mpdport; - const char *mpdhost; - const char *mpdpass; - const char *webport; + char *mpdhost; + char *mpdpass; + char *webport; bool ssl; - const char *sslport; - const char *sslcert; - const char *sslkey; - const char *user; + char *sslport; + char *sslcert; + char *sslkey; + char *user; bool coverimage; - const char *coverimagename; + char *coverimagename; long coverimagesize; bool stickers; bool mixramp; - const char *taglist; - const char *searchtaglist; - const char *browsetaglist; + char *taglist; + char *searchtaglist; + char *browsetaglist; bool smartpls; - const char *varlibdir; - const char *etcdir; + char *varlibdir; + char *etcdir; unsigned long max_elements_per_page; bool syscmds; bool localplayer; long streamport; - const char *streamurl; + char *streamurl; unsigned long last_played_count; long loglevel; - const char *backgroundcolor; + char *backgroundcolor; } t_config; //global functions @@ -194,6 +194,4 @@ bool validate_string(const char *data); int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len); int replacechar(char *str, const char orig, const char rep); enum mympd_cmd_ids get_cmd_id(const char *cmd); -bool state_file_read(t_config *config, const char *name, char *value); -bool state_file_write(t_config *config, const char *name, const char *value); #endif diff --git a/src/main.c b/src/main.c index 3e4aa5f..3d6b50f 100644 --- a/src/main.c +++ b/src/main.c @@ -47,6 +47,8 @@ static void signal_handler(int sig_num) { signal(sig_num, signal_handler); // Reinstantiate signal handler s_signal_received = sig_num; + //Wakeup mympd_api_loop + pthread_cond_signal(&mympd_api_queue->wakeup); } static int inihandler(void *user, const char *section, const char *name, const char* value) { @@ -55,61 +57,78 @@ static int inihandler(void *user, const char *section, const char *name, const c #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 - if (MATCH("mpd", "mpdhost")) + if (MATCH("mpd", "mpdhost")) { + free(p_config->mpdhost); p_config->mpdhost = strdup(value); - else if (MATCH("mpd", "mpdport")) + } + else if (MATCH("mpd", "mpdport")) { p_config->mpdport = strtol(value, &crap, 10); - else if (MATCH("mpd", "mpdpass")) + } + else if (MATCH("mpd", "mpdpass")) { + free(p_config->mpdpass); p_config->mpdpass = strdup(value); - else if (MATCH("mpd", "streamport")) + } + else if (MATCH("mpd", "streamport")) { p_config->streamport = strtol(value, &crap, 10); - else if (MATCH("webserver", "webport")) + } + else if (MATCH("webserver", "webport")) { + free(p_config->webport); p_config->webport = strdup(value); - else if (MATCH("webserver", "ssl")) - if (strcmp(value, "true") == 0) - p_config->ssl = true; - else - p_config->ssl = false; - else if (MATCH("webserver", "sslport")) + } + else if (MATCH("webserver", "ssl")) { + p_config->ssl = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("webserver", "sslport")) { + free(p_config->sslport); p_config->sslport = strdup(value); - else if (MATCH("webserver", "sslcert")) + } + else if (MATCH("webserver", "sslcert")) { + free(p_config->sslcert); p_config->sslcert = strdup(value); - else if (MATCH("webserver", "sslkey")) + } + else if (MATCH("webserver", "sslkey")) { + free(p_config->sslkey); p_config->sslkey = strdup(value); - else if (MATCH("mympd", "user")) + } + else if (MATCH("mympd", "user")) { + free(p_config->user); p_config->user = strdup(value); - else if (MATCH("mympd", "coverimage")) - if (strcmp(value, "true") == 0) - p_config->coverimage = true; - else - p_config->coverimage = false; - else if (MATCH("mympd", "coverimagename")) + } + else if (MATCH("mympd", "coverimage")) { + p_config->coverimage = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "coverimagename")) { + free(p_config->coverimagename); p_config->coverimagename = strdup(value); - else if (MATCH("mympd", "coverimagesize")) + } + else if (MATCH("mympd", "coverimagesize")) { p_config->coverimagesize = strtol(value, &crap, 10); - else if (MATCH("mympd", "varlibdir")) + } + else if (MATCH("mympd", "varlibdir")) { + free(p_config->varlibdir); p_config->varlibdir = strdup(value); - else if (MATCH("mympd", "stickers")) - if (strcmp(value, "true") == 0) - p_config->stickers = true; - else - p_config->stickers = false; - else if (MATCH("mympd", "smartpls")) - if (strcmp(value, "true") == 0) - p_config->smartpls = true; - else - p_config->smartpls = false; - else if (MATCH("mympd", "mixramp")) - if (strcmp(value, "true") == 0) - p_config->mixramp = true; - else - p_config->mixramp = false; - else if (MATCH("mympd", "taglist")) + } + else if (MATCH("mympd", "stickers")) { + p_config->stickers = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "smartpls")) { + p_config->smartpls = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "mixramp")) { + p_config->mixramp = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "taglist")) { + free(p_config->taglist); p_config->taglist = strdup(value); - else if (MATCH("mympd", "searchtaglist")) - p_config->searchtaglist = strdup(value); - else if (MATCH("mympd", "browsetaglist")) + } + else if (MATCH("mympd", "searchtaglist")) { + free(p_config->searchtaglist); + p_config->searchtaglist = strdup(value); + } + else if (MATCH("mympd", "browsetaglist")) { + free(p_config->browsetaglist); p_config->browsetaglist = strdup(value); + } else if (MATCH("mympd", "max_elements_per_page")) { p_config->max_elements_per_page = strtol(value, &crap, 10); if (p_config->max_elements_per_page > MAX_ELEMENTS_PER_PAGE) { @@ -117,27 +136,29 @@ static int inihandler(void *user, const char *section, const char *name, const c p_config->max_elements_per_page = MAX_ELEMENTS_PER_PAGE; } } - else if (MATCH("mympd", "syscmds")) - if (strcmp(value, "true") == 0) - p_config->syscmds = true; - else - p_config->syscmds = false; - else if (MATCH("mympd", "localplayer")) - if (strcmp(value, "true") == 0) - p_config->localplayer = true; - else - p_config->localplayer = false; - else if (MATCH("mympd", "streamurl")) + else if (MATCH("mympd", "syscmds")) { + p_config->syscmds = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "localplayer")) { + p_config->localplayer = strcmp(value, "true") == 0 ? true : false; + } + else if (MATCH("mympd", "streamurl")) { + free(p_config->streamurl); p_config->streamurl = strdup(value); - else if (MATCH("mympd", "last_played_count")) + } + else if (MATCH("mympd", "last_played_count")) { p_config->last_played_count = strtol(value, &crap, 10); - else if (MATCH("mympd", "loglevel")) + } + else if (MATCH("mympd", "loglevel")) { p_config->loglevel = strtol(value, &crap, 10); - else if (MATCH("theme", "backgroundcolor")) + } + else if (MATCH("theme", "backgroundcolor")) { + free(p_config->backgroundcolor); p_config->backgroundcolor = strdup(value); + } else { printf("Unkown config option: %s - %s\n", section, name); - return 0; /* unknown section/name, error */ + return 0; } return 1; @@ -154,26 +175,26 @@ int main(int argc, char **argv) { //mympd config defaults t_config config; - config.mpdhost = "127.0.0.1"; + config.mpdhost = strdup("127.0.0.1"); config.mpdport = 6600; config.mpdpass = NULL; - config.webport = "80"; + config.webport = strdup("80"); config.ssl = true; - config.sslport = "443"; - config.sslcert = "/etc/mympd/ssl/server.pem"; - config.sslkey = "/etc/mympd/ssl/server.key"; - config.user = "mympd"; + config.sslport = strdup("443"); + config.sslcert = strdup("/etc/mympd/ssl/server.pem"); + config.sslkey = strdup("/etc/mympd/ssl/server.key"); + config.user = strdup("mympd"); config.streamport = 8000; - config.streamurl = ""; + config.streamurl = strdup(""); config.coverimage = true; - config.coverimagename = "folder.jpg"; + config.coverimagename = strdup("folder.jpg"); config.coverimagesize = 240; - config.varlibdir = "/var/lib/mympd"; + config.varlibdir = strdup("/var/lib/mympd"); config.stickers = true; config.mixramp = true; - config.taglist = "Artist,Album,AlbumArtist,Title,Track,Genre,Date,Composer,Performer"; - config.searchtaglist = "Artist,Album,AlbumArtist,Title,Genre,Composer,Performer"; - config.browsetaglist = "Artist,Album,AlbumArtist,Genre,Composer,Performer"; + config.taglist = strdup("Artist,Album,AlbumArtist,Title,Track,Genre,Date,Composer,Performer"); + config.searchtaglist = strdup("Artist,Album,AlbumArtist,Title,Genre,Composer,Performer"); + config.browsetaglist = strdup("Artist,Album,AlbumArtist,Genre,Composer,Performer"); config.smartpls = true; config.max_elements_per_page = 100; config.last_played_count = 20; @@ -183,7 +204,7 @@ int main(int argc, char **argv) { config.syscmds = false; config.localplayer = true; config.loglevel = 1; - config.backgroundcolor = "#888"; + config.backgroundcolor = strdup("#888"); if (argc == 2) { printf("Starting myMPD %s\n", MYMPD_VERSION); @@ -292,9 +313,25 @@ int main(int argc, char **argv) { //cleanup pthread_join(mpd_client_thread, NULL); pthread_join(web_server_thread, NULL); + pthread_join(mympd_api_thread, NULL); tiny_queue_free(web_server_queue); tiny_queue_free(mpd_client_queue); tiny_queue_free(mympd_api_queue); + free(config.mpdhost); + free(config.mpdpass); + free(config.webport); + free(config.sslport); + free(config.sslcert); + free(config.sslkey); + free(config.user); + free(config.coverimagename); + free(config.taglist); + free(config.searchtaglist); + free(config.browsetaglist); + free(config.varlibdir); + free(config.etcdir); + free(config.streamurl); + free(config.backgroundcolor); return EXIT_SUCCESS; } diff --git a/src/mpd_client.c b/src/mpd_client.c index a94be35..1981a0c 100644 --- a/src/mpd_client.c +++ b/src/mpd_client.c @@ -1122,6 +1122,7 @@ static void mpd_client_idle(t_config *config, t_mpd_state *mpd_state) { len = snprintf(buffer, MAX_SIZE, "{\"type\": \"disconnected\"}"); mpd_client_notify(buffer, len); mpd_state->conn_state = MPD_FAILURE; + mpd_connection_free(mpd_state->conn); sleep(3); return; } @@ -1160,8 +1161,9 @@ static void mpd_client_idle(t_config *config, t_mpd_state *mpd_state) { // fall through case MPD_DISCONNECT: case MPD_RECONNECT: - if (mpd_state->conn != NULL) + if (mpd_state->conn != NULL) { mpd_connection_free(mpd_state->conn); + } mpd_state->conn = NULL; mpd_state->conn_state = MPD_DISCONNECTED; break; @@ -2557,7 +2559,9 @@ static int mpd_client_put_stats(t_mpd_state *mpd_state, char *buffer) { static void mpd_client_disconnect(t_config *config, t_mpd_state *mpd_state) { mpd_state->conn_state = MPD_DISCONNECT; -// mpd_client_idle(config, mpd_state); + if (mpd_state->conn != NULL) { + mpd_connection_free(mpd_state->conn); + } } static int mpd_client_smartpls_put(t_config *config, char *buffer, const char *playlist) { diff --git a/src/mympd_api.c b/src/mympd_api.c index e4bfe75..60ae397 100644 --- a/src/mympd_api.c +++ b/src/mympd_api.c @@ -69,6 +69,10 @@ static void mympd_api(t_config *config, t_mympd_state *mympd_state, t_work_reque static bool mympd_api_read_syscmds(t_config *config, t_mympd_state *mympd_state); static int mympd_api_syscmd(t_config *config, t_mympd_state *mympd_state, char *buffer, const char *cmd); static void mympd_api_read_statefiles(t_config *config, t_mympd_state *mympd_state); +static char *state_file_rw_string(t_config *config, const char *name, const char *def_value); +static bool state_file_rw_bool(t_config *config, const char *name, const bool def_value); +static long state_file_rw_long(t_config *config, const char *name, const long def_value); +static bool state_file_write(t_config *config, const char *name, const char *value); static int mympd_api_put_settings(t_config *config, t_mympd_state *mympd_state, char *buffer); @@ -327,112 +331,129 @@ static int mympd_api_syscmd(t_config *config, t_mympd_state *mympd_state, char * } static void mympd_api_read_statefiles(t_config *config, t_mympd_state *mympd_state) { - char *crap; - char value[400]; - LOG_INFO() printf("Reading states\n"); - if (state_file_read(config, "notificationWeb", value)) { - if (strcmp(value, "true") == 0) - mympd_state->notificationWeb = true; - else - mympd_state->notificationWeb = false; - } - else { - mympd_state->notificationWeb = false; - state_file_write(config, "notificationWeb", "false"); - } + mympd_state->notificationWeb = state_file_rw_bool(config, "notificationWeb", false); + mympd_state->notificationPage = state_file_rw_bool(config, "notificationPage", true); + mympd_state->autoPlay = state_file_rw_bool(config, "autoPlay", false); + mympd_state->jukeboxMode = state_file_rw_long(config, "jukeboxMode", JUKEBOX_OFF); + mympd_state->jukeboxPlaylist = state_file_rw_string(config, "jukeboxPlaylist", "Database"); + mympd_state->jukeboxQueueLength = state_file_rw_long(config, "jukeboxQueueLength", 1); + mympd_state->colsQueueCurrent = state_file_rw_string(config, "colsQueueCurrent", "[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); + mympd_state->colsSearch = state_file_rw_string(config, "colsSearch", "[\"Title\",\"Artist\",\"Album\",\"Duration\"]"); + mympd_state->colsBrowseDatabase = state_file_rw_string(config, "colsBrowseDatabase", "[\"Track\",\"Title\",\"Duration\"]"); + mympd_state->colsBrowsePlaylistsDetail = state_file_rw_string(config, "colsBrowsePlaylistsDetail", "[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); + mympd_state->colsBrowseFilesystem = state_file_rw_string(config, "colsBrowseFilesystem", "[\"Type\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); + mympd_state->colsPlayback = state_file_rw_string(config, "colsPlayback", "[\"Artist\",\"Album\"]"); + mympd_state->colsQueueLastPlayed = state_file_rw_string(config, "colsQueueLastPlayed", "[\"Pos\",\"Title\",\"Artist\",\"Album\",\"LastPlayed\"]"); +} - if (state_file_read(config, "notificationPage", value)) { - if (strcmp(value, "true") == 0) - mympd_state->notificationPage = true; - else - mympd_state->notificationPage = false; +static char *state_file_rw_string(t_config *config, const char *name, const char *def_value) { + char cfg_file[400]; + char *line = NULL; + size_t n = 0; + ssize_t read; + + if (!validate_string(name)) { + return NULL; + } + snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); + FILE *fp = fopen(cfg_file, "r"); + if (fp == NULL) { + printf("Error opening %s\n", cfg_file); + state_file_write(config, name, def_value); + return NULL; + } + read = getline(&line, &n, fp); + if (read > 0) { + LOG_DEBUG() fprintf(stderr, "DEBUG: State %s: %s\n", name, line); + } + fclose(fp); + if (read > 0) { + return line; } else { - mympd_state->notificationPage = true; - state_file_write(config, "notificationPage", "true"); + free(line); + return NULL; } +} - if (state_file_read(config, "autoPlay", value)) { - if (strcmp(value, "true") == 0) - mympd_state->autoPlay = true; - else - mympd_state->autoPlay = false; - } - else { - mympd_state->autoPlay = false; - state_file_write(config, "autoPlay", "false"); - } +static bool state_file_rw_bool(t_config *config, const char *name, const bool def_value) { + char cfg_file[400]; + char *line = NULL; + size_t n = 0; + ssize_t read; + bool value = def_value; - if (state_file_read(config, "jukeboxMode", value)) - mympd_state->jukeboxMode = strtol(value, &crap, 10); - else { - mympd_state->jukeboxMode = JUKEBOX_OFF; - state_file_write(config, "jukeboxMode", "0"); + if (!validate_string(name)) + return def_value; + snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); + FILE *fp = fopen(cfg_file, "r"); + if (fp == NULL) { + printf("Error opening %s\n", cfg_file); + state_file_write(config, name, def_value == true ? "true" : "false"); + return def_value; } + read = getline(&line, &n, fp); + if (read > 0) { + LOG_DEBUG() fprintf(stderr, "DEBUG: State %s: %s\n", name, line); + value = strcmp(line, "true") == 0 ? true : false; + } + fclose(fp); + free(line); + return value; +} - if (state_file_read(config, "jukeboxPlaylist", value)) - mympd_state->jukeboxPlaylist = strdup(value); - else { - mympd_state->jukeboxPlaylist = strdup("Database"); - state_file_write(config, "jukeboxPlaylist", "Database"); +static long state_file_rw_long(t_config *config, const char *name, const long def_value) { + char cfg_file[400]; + char *line = NULL; + char *crap; + size_t n = 0; + ssize_t read; + long value = def_value; + + if (!validate_string(name)) + return def_value; + snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); + FILE *fp = fopen(cfg_file, "r"); + if (fp == NULL) { + printf("Error opening %s\n", cfg_file); + char p_value[65]; + snprintf(p_value, 65, "%ld", def_value); + state_file_write(config, name, p_value); + return def_value; } + read = getline(&line, &n, fp); + if (read > 0) { + LOG_DEBUG() fprintf(stderr, "DEBUG: State %s: %s\n", name, line); + value = strtol(line, &crap, 10); + } + fclose(fp); + free(line); + return value; +} - if (state_file_read(config, "jukeboxQueueLength", value)) - mympd_state->jukeboxQueueLength = strtol(value, &crap, 10); - else { - mympd_state->jukeboxQueueLength = 1; - state_file_write(config, "jukeboxQueueLength", "1"); - } - - if (state_file_read(config, "colsQueueCurrent", value)) - mympd_state->colsQueueCurrent = strdup(value); - else { - mympd_state->colsQueueCurrent = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); - state_file_write(config, "colsQueueCurrent", mympd_state->colsQueueCurrent); - } - - if (state_file_read(config, "colsSearch", value)) - mympd_state->colsSearch = strdup(value); - else { - mympd_state->colsSearch = strdup("[\"Title\",\"Artist\",\"Album\",\"Duration\"]"); - state_file_write(config, "colsSearch", mympd_state->colsSearch); - } - - if (state_file_read(config, "colsBrowseDatabase", value)) - mympd_state->colsBrowseDatabase = strdup(value); - else { - mympd_state->colsBrowseDatabase = strdup("[\"Track\",\"Title\",\"Duration\"]"); - state_file_write(config, "colsBrowseDatabase", mympd_state->colsBrowseDatabase); - } - - if (state_file_read(config, "colsBrowsePlaylistsDetail", value)) - mympd_state->colsBrowsePlaylistsDetail = strdup(value); - else { - mympd_state->colsBrowsePlaylistsDetail = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); - state_file_write(config, "colsBrowsePlaylistsDetail", mympd_state->colsBrowsePlaylistsDetail); - } - - if (state_file_read(config, "colsBrowseFilesystem", value)) - mympd_state->colsBrowseFilesystem = strdup(value); - else { - mympd_state->colsBrowseFilesystem = strdup("[\"Type\",\"Title\",\"Artist\",\"Album\",\"Duration\"]"); - state_file_write(config, "colsBrowseFilesystem", mympd_state->colsBrowseFilesystem); - } - - if (state_file_read(config, "colsPlayback", value)) - mympd_state->colsPlayback = strdup(value); - else { - mympd_state->colsPlayback = strdup("[\"Artist\",\"Album\",\"Genre\"]"); - state_file_write(config, "colsPlayback", mympd_state->colsPlayback); - } - if (state_file_read(config, "colsQueueLastPlayed", value)) - mympd_state->colsQueueLastPlayed = strdup(value); - else { - mympd_state->colsQueueLastPlayed = strdup("[\"Pos\",\"Title\",\"Artist\",\"Album\",\"LastPlayed\"]"); - state_file_write(config, "colsQueueLastPlayed", mympd_state->colsQueueLastPlayed); +static bool state_file_write(t_config *config, const char *name, const char *value) { + char tmp_file[400]; + char cfg_file[400]; + + if (!validate_string(name)) + return false; + snprintf(cfg_file, 400, "%s/state/%s", config->varlibdir, name); + snprintf(tmp_file, 400, "%s/tmp/%s", config->varlibdir, name); + + FILE *fp = fopen(tmp_file, "w"); + if (fp == NULL) { + printf("Error opening %s\n", tmp_file); + return false; } + fprintf(fp, "%s", value); + fclose(fp); + if (rename(tmp_file, cfg_file) == -1) { + printf("Error renaming file from %s to %s\n", tmp_file, cfg_file); + return false; + } + return true; } static int mympd_api_put_settings(t_config *config, t_mympd_state *mympd_state, char *buffer) { diff --git a/src/tiny_queue.c b/src/tiny_queue.c index 7bc95ac..c7f9532 100644 --- a/src/tiny_queue.c +++ b/src/tiny_queue.c @@ -152,19 +152,28 @@ void *tiny_queue_shift(tiny_queue_t *queue, int timeout) { } } //queue has entry - struct tiny_msg_t* current_head = queue->head; - void *data = current_head->data; - if (queue->head == queue->tail) { - queue->head = queue->tail = NULL; + if (queue->head != NULL) { + struct tiny_msg_t* current_head = queue->head; + void *data = current_head->data; + if (queue->head == queue->tail) { + queue->head = queue->tail = NULL; + } + else { + queue->head = queue->head->next; + } + free(current_head); + queue->length--; + rc = pthread_mutex_unlock(&queue->mutex); + if (rc != 0) { + printf("Error in pthread_mutex_unlock: %d\n", rc); + } + return data; } else { - queue->head = queue->head->next; + rc = pthread_mutex_unlock(&queue->mutex); + if (rc != 0) { + printf("Error in pthread_mutex_unlock: %d\n", rc); + } + return NULL; } - free(current_head); - queue->length--; - rc = pthread_mutex_unlock(&queue->mutex); - if (rc != 0) { - printf("Error in pthread_mutex_unlock: %d\n", rc); - } - return data; }