Merge commit 'fml/master'
authorAndre Noll <maan@systemlinux.org>
Tue, 10 Feb 2009 07:44:02 +0000 (08:44 +0100)
committerAndre Noll <maan@systemlinux.org>
Tue, 10 Feb 2009 07:44:02 +0000 (08:44 +0100)
afs.c
afs.cmd
attribute.c
server.c

diff --git a/afs.c b/afs.c
index b8acb53a9ffa2782e8fc0421a9a01f5642347eed..f4a44bbbe0af852a61d81488bfe2274e0879a52d 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -141,6 +141,36 @@ struct callback_result {
        size_t result_size;
 };
 
+static int dispatch_result(int result_shmid, callback_result_handler *handler,
+               void *private_result_data)
+{
+       struct osl_object result;
+       void *result_shm;
+       int ret2, ret = shm_attach(result_shmid, ATTACH_RO, &result_shm);
+       struct callback_result *cr = result_shm;
+
+       if (ret < 0) {
+               PARA_ERROR_LOG("attach failed: %s\n", para_strerror(-ret));
+               return ret;
+       }
+       result.size = cr->result_size;
+       result.data = result_shm + sizeof(*cr);
+       if (result.size) {
+               assert(handler);
+               ret = handler(&result, private_result_data);
+               if (ret < 0)
+                       PARA_NOTICE_LOG("result handler error: %s\n",
+                               para_strerror(-ret));
+       }
+       ret2 = shm_detach(result_shm);
+       if (ret2 < 0) {
+               PARA_ERROR_LOG("detach failed: %s\n", para_strerror(-ret2));
+               if (ret >= 0)
+                       ret = ret2;
+       }
+       return ret;
+}
+
 /**
  * Ask the afs process to call a given function.
  *
@@ -161,8 +191,7 @@ struct callback_result {
  * shmid are passed to that function as an osl object. The private_result_data
  * pointer is passed as the second argument to \a result_handler.
  *
- * \return Negative, on errors, the return value of the callback function
- * otherwise.
+ * \return Standard.
  *
  * \sa send_option_arg_callback_request(), send_standard_callback_request().
  */
@@ -171,10 +200,11 @@ int send_callback_request(callback_function *f, struct osl_object *query,
                void *private_result_data)
 {
        struct callback_query *cq;
-       int num_results = 0, ret, fd = -1, query_shmid, result_shmid;
-       void *query_shm, *result_shm;
+       int ret, fd = -1, query_shmid, result_shmid;
+       void *query_shm;
        char buf[sizeof(afs_socket_cookie) + sizeof(int)];
        size_t query_shm_size = sizeof(*cq);
+       int dispatch_error = 0;
 
        if (query)
                query_shm_size += query->size;
@@ -205,45 +235,37 @@ int send_callback_request(callback_function *f, struct osl_object *query,
        ret = send_bin_buffer(fd, buf, sizeof(buf));
        if (ret < 0)
                goto out;
+       /*
+        * Read all shmids from afs.
+        *
+        * Even if the dispatcher returns an error we _must_ continue to read
+        * shmids from fd so that we can destroy all shared memory areas that
+        * have been created for us by the afs process.
+        */
        for (;;) {
                ret = recv_bin_buffer(fd, buf, sizeof(int));
                if (ret <= 0)
                        goto out;
-               if (ret != sizeof(int)) {
-                       ret = -E_AFS_SHORT_READ;
-                       goto out;
-               }
+               assert(ret == sizeof(int));
                ret = *(int *) buf;
-               if (ret <= 0)
-                       goto out;
+               assert(ret > 0);
                result_shmid = ret;
-               ret = shm_attach(result_shmid, ATTACH_RO, &result_shm);
-               if (ret >= 0) {
-                       struct callback_result *cr = result_shm;
-                       struct osl_object result;
-                       num_results++;
-                       result.size = cr->result_size;
-                       result.data = result_shm + sizeof(*cr);
-                       if (result.size) {
-                               assert(result_handler);
-                               ret = result_handler(&result, private_result_data);
-                               if (shm_detach(result_shm) < 0)
-                                       PARA_ERROR_LOG("can not detach result\n");
-                       }
-               } else
-                       PARA_ERROR_LOG("attach result failed: %d\n", ret);
-               if (shm_destroy(result_shmid) < 0)
-                       PARA_ERROR_LOG("destroy result failed\n");
+               if (!dispatch_error) {
+                       ret = dispatch_result(result_shmid, result_handler,
+                               private_result_data);
+                       if (ret < 0)
+                               dispatch_error = 1;
+               }
+               ret = shm_destroy(result_shmid);
                if (ret < 0)
-                       break;
+                       PARA_CRIT_LOG("destroy result failed: %s\n",
+                               para_strerror(-ret));
        }
 out:
        if (shm_destroy(query_shmid) < 0)
-               PARA_ERROR_LOG("%s\n", "shm destroy error");
+               PARA_CRIT_LOG("shm destroy error\n");
        if (fd >= 0)
                close(fd);
-       if (ret >= 0)
-               ret = num_results;
 //     PARA_DEBUG_LOG("callback_ret: %d\n", ret);
        return ret;
 }
@@ -787,10 +809,6 @@ static void register_signal_task(void)
                PARA_EMERG_LOG("failed to ignore SIGPIPE\n");
                exit(EXIT_FAILURE);
        }
-       if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
-               PARA_EMERG_LOG("failed to ignore SIGUSR1\n");
-               exit(EXIT_FAILURE);
-       }
        st->fd = para_signal_init();
        PARA_INFO_LOG("signal pipe: fd %d\n", st->fd);
        para_install_sighandler(SIGINT);
diff --git a/afs.cmd b/afs.cmd
index 5c9f1ecb5c78cd01a8dbcf86b7adc5cd4e6449d5..da4b3f86030a299e477093de629595849b2b0173 100644 (file)
--- a/afs.cmd
+++ b/afs.cmd
@@ -56,6 +56,8 @@ H:            -lv:   verbose listing mode
 H:
 H:             -lm:   mbox listing mode
 H:
+H:             -lc:   chunk-table listing mode
+H:
 H: -p  List full path of audio file. If not specified, only the basename
 H:     of each file is printed.
 H:
index d22511de76f92f19835b6c5c57faa54ba9360eab..cce8ce6e03bd9aef9d675de1ef79a983a294413b 100644 (file)
@@ -568,8 +568,7 @@ void attribute_close(void)
 /**
  * Open the attribute table.
  *
- * \param ti Gets initialized by this function.
- * \param db The database directory.
+ * \param dir The database directory.
  *
  * \return Positive on success, negative on errors.
  *
index 9187b63fa6ae20aa525fa435010f1675b1458b0d..9c06991378512172e95b70165118ae1ea873bdb1 100644 (file)
--- a/server.c
+++ b/server.c
@@ -328,8 +328,6 @@ static void init_signal_task(void)
                goto err;
        if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
                goto err;
-       if (signal(SIGUSR1, SIG_IGN) == SIG_ERR)
-               goto err;
        add_close_on_fork_list(st->fd);
        register_task(&st->task);
        return;
@@ -499,6 +497,18 @@ static void server_init(int argc, char **argv)
                daemonize();
        PARA_NOTICE_LOG("initializing audio format handlers\n");
        afh_init();
+
+       /*
+        * Although afs uses its own signal handling we must ignore SIGUSR1
+        * _before_ the afs child process gets born by init_afs() below.  It's
+        * racy to do this in the child because the parent might send SIGUSR1
+        * before the child gets a chance to ignore this signal -- only the
+        * good die young.
+        */
+       if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
+               PARA_EMERG_LOG("failed to ignore SIGUSR1\n");
+               exit(EXIT_FAILURE);
+       }
        PARA_NOTICE_LOG("initializing the audio file selector\n");
        afs_socket = init_afs();
        init_signal_task();