]> git.tue.mpg.de Git - paraslash.git/commitdiff
Fix handling of invalid entries in the score table.
authorAndre Noll <maan@systemlinux.org>
Sun, 18 Nov 2007 19:59:49 +0000 (20:59 +0100)
committerAndre Noll <maan@systemlinux.org>
Sun, 18 Nov 2007 19:59:49 +0000 (20:59 +0100)
It may happen that the score table contains references to files that
no longer exist in the file system. The current code fails badly in
this case.

In open_next_audio_file(), if the file corresponding to the next
entry in the score table can not be opened, delete this entry from
the score table and try the next entry.

If the score table becomes empty, send NO_ADMISSIBLE_FILES back to para_server
and make recv_afs_result() switch to stop mode in this case.

afs.c
afs.h
error.h
vss.c

diff --git a/afs.c b/afs.c
index 353626ee7cd37602e1faaeb37004ba278eb9e3f1..8a60166fe7e42d5f5762cb46547a9413df6bd342 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -487,17 +487,26 @@ int open_next_audio_file(void)
        int ret, shmid;
        char buf[8];
        long score;
-
+again:
        PARA_NOTICE_LOG("getting next audio file\n");
        ret = score_get_best(&aft_row, &score);
-       if (ret < 0)
-               return ret;
+       if (ret < 0) {
+               PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+               goto no_admissible_files;
+       }
        ret = open_and_update_audio_file(aft_row, score, &afd);
-       if (ret < 0)
-               return ret;
+       if (ret < 0) {
+               PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+               ret = score_delete(aft_row);
+               if (ret < 0) {
+                       PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+                       goto no_admissible_files;
+               }
+               goto again;
+       }
        shmid = ret;
        if (!write_ok(server_socket)) {
-               PARA_EMERG_LOG("afs_socket not writable\n");
+               ret = -E_AFS_SOCKET;
                goto destroy;
        }
        *(uint32_t *)buf = NEXT_AUDIO_FILE;
@@ -506,10 +515,13 @@ int open_next_audio_file(void)
        close(afd.fd);
        if (ret >= 0)
                return ret;
-       PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
 destroy:
        shm_destroy(shmid);
        return ret;
+no_admissible_files:
+       *(uint32_t *)buf = NO_ADMISSIBLE_FILES;
+       *(uint32_t *)(buf + 4) = (uint32_t)0;
+       return send_bin_buffer(server_socket, buf, 8);
 }
 
 /* Never fails if arg == NULL */
@@ -846,8 +858,10 @@ static void execute_server_command(void)
        PARA_DEBUG_LOG("received: %s\n", buf);
        if (!strcmp(buf, "new")) {
                ret = open_next_audio_file();
-               if (ret < 0)
-                       PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+               if (ret < 0) {
+                       PARA_EMERG_LOG("%s\n", PARA_STRERROR(-ret));
+                       unregister_tasks();
+               }
                return;
        }
        PARA_ERROR_LOG("unknown command\n");
diff --git a/afs.h b/afs.h
index 7aea5cb28950305252deddfe37e9c40fde88fa92..977fc40b6591dd778294ce7a796a6edcb4746f18 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -126,6 +126,7 @@ struct audio_file_data {
 
 enum afs_server_code {
        NEXT_AUDIO_FILE,
+       NO_ADMISSIBLE_FILES,
        AFD_CHANGE
 };
 
diff --git a/error.h b/error.h
index 3e4911bf6c07ca85e4e675b1d3acacec37b24163..f1a3e41dd7ef84b54280b54d3a759a08e4397845 100644 (file)
--- a/error.h
+++ b/error.h
@@ -84,6 +84,7 @@ extern const char **para_errlist[];
        PARA_ERROR(INPUT_TOO_LARGE, "input too large for stdin command"), \
        PARA_ERROR(AFS_SYNTAX, "afs syntax error"), \
        PARA_ERROR(AFS_SIGNAL, "afs caught deadly signal"), \
+       PARA_ERROR(AFS_SOCKET, "afs socket not writable"), \
        PARA_ERROR(AFS_PARENT_DIED, "fatal: server process terminated"), \
 
 
@@ -314,7 +315,7 @@ extern const char **para_errlist[];
        PARA_ERROR(AUDIO_FORMAT, "audio format not recognized"), \
        PARA_ERROR(CHUNK, "unable to get chunk"), \
        PARA_ERROR(SHORT_AFS_READ, "short read from afs socket"), \
-       PARA_ERROR(BAD_AFS_CODE, "received junk from afs"), \
+       PARA_ERROR(NOFD, "did not receive open fd from afs"), \
 
 
 #define CRYPT_ERRORS \
diff --git a/vss.c b/vss.c
index 46fb3196c4c2155be65b361e9f1fb31715693e19..efd0c5ea8e43402fc85f801fc87f039674cf91a8 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -345,6 +345,7 @@ static int recv_afs_msg(int *fd, uint32_t *code, uint32_t *data)
        struct iovec iov;
        int ret = 0;
 
+       *fd = -1;
        iov.iov_base = buf;
        iov.iov_len = sizeof(buf);
        msg.msg_iov = &iov;
@@ -355,6 +356,7 @@ static int recv_afs_msg(int *fd, uint32_t *code, uint32_t *data)
        ret = recvmsg(afs_socket, &msg, 0);
        if (ret < 0)
                return -ERRNO_TO_PARA_ERROR(errno);
+       afsss = AFS_SOCKET_READY;
        if (iov.iov_len != sizeof(buf))
                return -E_SHORT_AFS_READ;
        *code = *(uint32_t*)buf;
@@ -372,7 +374,7 @@ static int recv_afs_msg(int *fd, uint32_t *code, uint32_t *data)
 
 static void recv_afs_result(void)
 {
-       int ret, passed_fd = -1, shmid;
+       int ret, passed_fd, shmid;
        uint32_t afs_code = 0, afs_data = 0;
        struct stat statbuf;
        struct timeval now;
@@ -380,12 +382,13 @@ static void recv_afs_result(void)
        ret = recv_afs_msg(&passed_fd, &afs_code, &afs_data);
        if (ret < 0)
                goto err;
-       PARA_DEBUG_LOG("got the fd: %d, code: %u, shmid: %u\n",
-               passed_fd, afs_code, afs_data);
-       ret = -E_BAD_AFS_CODE;
+       PARA_DEBUG_LOG("fd: %d, code: %u, shmid: %u\n", passed_fd, afs_code,
+               afs_data);
+       ret = -E_NOFD;
        if (afs_code != NEXT_AUDIO_FILE)
                goto err;
-       afsss = AFS_SOCKET_READY;
+       if (passed_fd < 0)
+               goto err;
        shmid = afs_data;
        ret = load_afd(shmid, &mmd->afd);
        if (ret < 0)
@@ -415,6 +418,7 @@ err:
        if (passed_fd >= 0)
                close(passed_fd);
        PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
+       mmd->new_vss_status_flags = VSS_NEXT;
 }
 
 void vss_post_select(fd_set *rfds, fd_set *wfds)