From 3cdcb449fc23f0bebe34343dc26b4e34b82175d5 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 16 Apr 2018 20:41:39 +0200 Subject: [PATCH] aft: Remember current audio file after SIGHUP. The current_aft_row pointer becomes stale when the osl tables are re-opened because SIGHUP has been received. If the current audio file is renamed, or its metadate (afs info or afh info) are modified, the table event dispatcher of the audio file table compares the stale row pointer against the (non-stale) row pointer of the audio file that has been obtained by path lookup. The two pointers never compare equal under normal circumstances due to ASLR, so the file modification does not trigger an update of the status items. This patch fixes this inconvenience by remembering the hash of the current audio file at table close time. On SIGHUP, after the table has been re-opened, we lookup the stored hash to replace the stale row pointer. --- aft.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/aft.c b/aft.c index 5233fe96..944d904d 100644 --- a/aft.c +++ b/aft.c @@ -42,6 +42,7 @@ struct ls_data { */ static struct osl_table *audio_file_table; /* NULL if table not open */ static struct osl_row *current_aft_row; /* NULL if no audio file open */ +static unsigned char current_hash[HASH_SIZE]; /* only used on sighup */ static char *status_items; static char *parser_friendly_status_items; @@ -2475,28 +2476,30 @@ int aft_check_attributes(uint64_t att_mask, struct para_buffer *pb) return audio_file_loop(&acad, check_atts_of_audio_file); } -/** - * Close the audio file table. - * - * \param flags Usual flags that are passed to osl_close_table(). - * - * \sa \ref osl_close_table(). +/* + * This sets audio_file_table to NULL, but leaves current_aft_row unmodified, + * though stale (pointing to unmapped memory). If the table is being closed + * because we received SIGHUP, the table will be reopened after the config file + * has been reloaded. We remember the hash of the current audio file here so + * that aft_open() can initialize current_aft_row by looking up the saved hash. */ static void aft_close(void) { + int ret; + unsigned char *p; + + if (current_aft_row) { + ret = get_hash_of_row(current_aft_row, &p); + if (ret < 0) { + PARA_WARNING_LOG("hash lookup failure\n"); + current_aft_row = NULL; + } else + memcpy(current_hash, p, HASH_SIZE); + } osl_close_table(audio_file_table, OSL_MARK_CLEAN); audio_file_table = NULL; } -/** - * Open the audio file table. - * - * \param dir The database directory. - * - * \return Standard. - * - * \sa \ref osl_open_table(). - */ static int aft_open(const char *dir) { int ret; @@ -2507,7 +2510,20 @@ static int aft_open(const char *dir) unsigned num; osl_get_num_rows(audio_file_table, &num); PARA_INFO_LOG("audio file table contains %u files\n", num); - return ret; + if (!current_aft_row) { + PARA_DEBUG_LOG("no current aft row\n"); + return 1; + } + /* SIGHUP case, update current_aft_row */ + ret = aft_get_row_of_hash(current_hash, ¤t_aft_row); + if (ret < 0) { /* not fatal */ + PARA_WARNING_LOG("current hash lookup failure: %s\n", + para_strerror(-ret)); + current_aft_row = NULL; + return 1; + } + PARA_NOTICE_LOG("current audio file hash lookup: success\n"); + return 1; } PARA_NOTICE_LOG("failed to open audio file table\n"); audio_file_table = NULL; -- 2.39.2