aft: Remember current audio file after SIGHUP.
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 16 Apr 2018 18:41:39 +0000 (20:41 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 6 May 2018 08:45:39 +0000 (10:45 +0200)
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

diff --git a/aft.c b/aft.c
index 5233fe9..944d904 100644 (file)
--- 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, &current_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;