From: Andre Noll Date: Sun, 18 Nov 2007 19:59:49 +0000 (+0100) Subject: Fix handling of invalid entries in the score table. X-Git-Tag: v0.3.0~113^2~3 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=965eae5ba6664349ff74977439f3214142a3bc9a Fix handling of invalid entries in the score table. 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. --- diff --git a/afs.c b/afs.c index 353626ee..8a60166f 100644 --- 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 7aea5cb2..977fc40b 100644 --- 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 3e4911bf..f1a3e41d 100644 --- 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 46fb3196..efd0c5ea 100644 --- 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)