diff --git a/src/command.c b/src/command.c index ae571a401..551012049 100644 --- a/src/command.c +++ b/src/command.c @@ -317,8 +317,7 @@ int handleSearch(FILE * fp, unsigned int * permission, int argArrayLength, int handleUpdate(FILE * fp, unsigned int * permission, int argArrayLength, char ** argArray) { - incrPlaylistVersion(); - return updateMp3Directory(fp); + return updateInit(fp); } int handleNext(FILE * fp, unsigned int * permission, int argArrayLength, diff --git a/src/directory.c b/src/directory.c index dd0f49b54..16f2c0fa0 100644 --- a/src/directory.c +++ b/src/directory.c @@ -26,14 +26,21 @@ #include "conf.h" #include "stats.h" #include "playlist.h" +#include "listen.h" +#include "interface.h" +#include "volume.h" #include #include +#include +#include +#include #include #include #include #include #include +#include #define DIRECTORY_DIR "directory: " #define DIRECTORY_MTIME "mtime: " @@ -63,6 +70,8 @@ Directory * mp3rootDirectory = NULL; char directorydb[MAXPATHLEN+1]; +int directory_updatePid = 0; + DirectoryList * newDirectoryList(); int addToDirectory(Directory * directory, char * shortname, char * name); @@ -79,6 +88,61 @@ void deleteEmptyDirectoriesInDirectory(Directory * directory); int addSubDirectoryToDirectory(Directory * directory, char * shortname, char * name); +void directory_sigChldHandler(int pid, int status) { + if(directory_updatePid==pid) { + if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { + ERROR("update process died from a " + "non-TERM signal: %i\n", + WTERMSIG(status)); + } + else if(WEXITSTATUS(status)==EXIT_SUCCESS) { + readDirectoryDB(); + incrPlaylistVersion(); + DEBUG("direcotry_sigChldHandler: " + "updated db succesffully\n"); + } + directory_updatePid = 0; + } +} + +int updateInit(FILE * fp) { + if(directory_updatePid > 0) { + myfprintf(fp,"%s already updating\n",COMMAND_RESPOND_ERROR); + return -1; + } + + directory_updatePid = fork(); + if(directory_updatePid==0) { + /* child */ + struct sigaction sa; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE,&sa,NULL); + sigaction(SIGCHLD,&sa,NULL); + + close(listenSocket); + freeAllInterfaces(); + finishPlaylist(); + finishVolume(); + + if(updateMp3Directory(stderr)) exit(EXIT_FAILURE); + exit(EXIT_SUCCESS); + } + else if(directory_updatePid < 0) { + ERROR("updateInit: Problems forking()'ing\n"); + myfprintf(fp,"%s problems trying to update\n", + COMMAND_RESPOND_ERROR); + directory_updatePid = 0; + return -1; + } + + DEBUG("updateInit: fork()'d update child\n"); + + return 0; +} + Directory * newDirectory(Directory * parentDirectory, char * dirname, time_t mtime) { Directory * directory; diff --git a/src/directory.h b/src/directory.h index f701fe81a..1ad2c1ab5 100644 --- a/src/directory.h +++ b/src/directory.h @@ -28,6 +28,10 @@ extern char directorydb[MAXPATHLEN+1]; +void directory_sigChldHandler(int pid, int status); + +int updateInit(FILE * fp); + void initMp3Directory(); void closeMp3Directory(); diff --git a/src/player.c b/src/player.c index 4efe55679..63ee4f062 100644 --- a/src/player.c +++ b/src/player.c @@ -66,29 +66,24 @@ void resetPlayer() { getPlayerData()->playerControl.decode_pid = 0; } -void player_sigHandler(int signal) { - if(signal==SIGCHLD) { - int status; - int pid = wait3(&status,WNOHANG,NULL); - if(player_pid==pid) { - if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { - ERROR("player process died from a " - "non-TERM signal: %i\n", - WTERMSIG(status)); - } - resetPlayer(); +void player_sigChldHandler(int pid, int status) { + if(player_pid==pid) { + if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { + ERROR("player process died from a " + "non-TERM signal: %i\n", + WTERMSIG(status)); } - else if(pid==getPlayerData()->playerControl.decode_pid && - player_pid<=0) - { - if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { - ERROR("(caught by master parent) " - "decode process died from a " - "non-TERM signal: %i\n", - WTERMSIG(status)); - } - getPlayerData()->playerControl.decode_pid = 0; + resetPlayer(); + } + else if(pid==getPlayerData()->playerControl.decode_pid && player_pid<=0) + { + if(WIFSIGNALED(status) && WTERMSIG(status)!=SIGTERM) { + ERROR("(caught by master parent) " + "decode process died from a " + "non-TERM signal: %i\n", + WTERMSIG(status)); } + getPlayerData()->playerControl.decode_pid = 0; } } diff --git a/src/player.h b/src/player.h index ca1cfa6a8..a52c511a0 100644 --- a/src/player.h +++ b/src/player.h @@ -79,7 +79,7 @@ typedef struct _PlayerControl { int decode_pid; } PlayerControl; -void player_sigHandler(int signal); +void player_sigChldHandler(int pid, int status); int playerPlay(FILE * fp, char * utf8file); diff --git a/src/playlist.c b/src/playlist.c index 957a4a748..856dea8fa 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -144,7 +144,9 @@ void finishPlaylist() { stopPlaylist(stderr); clearPlaylist(stderr); free(playlist.songs); + playlist.songs = NULL; free(playlist.order); + playlist.order = NULL; } int clearPlaylist(FILE * fp) { @@ -626,6 +628,8 @@ int deleteFromPlaylist(FILE * fp, int song) { void deleteASongFromPlaylist(Song * song) { int i; + + if(NULL==playlist.songs) return; for(i=0;i +#include +#include +#include +#include struct sigaction original_termSa; struct sigaction original_hupSa; @@ -41,6 +45,15 @@ void hupSigHandler(int signal) { readDirectoryDB(); } +void chldSigHandler(int signal) { + int status; + int pid = wait3(&status,WNOHANG,NULL); + if(pid>0) { + player_sigChldHandler(pid,status); + directory_sigChldHandler(pid,status); + } +} + void initSigHandlers() { struct sigaction sa; @@ -50,12 +63,14 @@ void initSigHandlers() { sigaction(SIGPIPE,&sa,NULL); sa.sa_handler = usr1SigHandler; sigaction(SIGUSR1,&sa,NULL); - sa.sa_handler = player_sigHandler; + sigaddset(&sa.sa_mask,SIGTERM); + sigaddset(&sa.sa_mask,SIGHUP); + sigaddset(&sa.sa_mask,SIGCHLD); + sa.sa_handler = chldSigHandler; sigaction(SIGCHLD,&sa,NULL); sa.sa_handler = hupSigHandler; sigaction(SIGHUP,&sa,&original_hupSa); sa.sa_handler = termSigHandler; - /*sigaddset(&sa.sa_mask,SIGTERM);*/ sigaction(SIGTERM,&sa,&original_termSa); } @@ -70,6 +85,7 @@ void blockSignals() { sigemptyset(&sset); sigaddset(&sset,SIGCHLD); sigaddset(&sset,SIGUSR1); + sigaddset(&sset,SIGHUP); sigprocmask(SIG_BLOCK,&sset,NULL); } @@ -79,6 +95,7 @@ void unblockSignals() { sigemptyset(&sset); sigaddset(&sset,SIGCHLD); sigaddset(&sset,SIGUSR1); + sigaddset(&sset,SIGHUP); sigprocmask(SIG_UNBLOCK,&sset,NULL); } @@ -87,6 +104,7 @@ void blockTermSignal() { sigemptyset(&sset); sigaddset(&sset,SIGTERM); + sigaddset(&sset,SIGHUP); sigprocmask(SIG_BLOCK,&sset,NULL); } @@ -95,5 +113,6 @@ void unblockTermSignal() { sigemptyset(&sset); sigaddset(&sset,SIGTERM); + sigaddset(&sset,SIGHUP); sigprocmask(SIG_UNBLOCK,&sset,NULL); }