diff --git a/inotify.c b/inotify.c index 2424005..ffc8e11 100644 --- a/inotify.c +++ b/inotify.c @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef HAVE_INOTIFY_H #include #else @@ -194,13 +195,18 @@ int inotify_remove_watches(int fd) { struct watch *w = watches; + struct watch *last_w; int rm_watches = 0; while( w ) { + last_w = w; inotify_rm_watch(fd, w->wd); + if( w->path ) + free(w->path); rm_watches++; w = w->next; + free(last_w); } return rm_watches; @@ -593,34 +599,49 @@ inotify_remove_directory(int fd, const char * path) void * start_inotify() { - int fd; + struct pollfd pollfds[1]; + int timeout = 1000; char buffer[BUF_LEN]; char path_buf[PATH_MAX]; int length, i = 0; char * esc_name = NULL; struct stat st; - fd = inotify_init(); + pollfds[0].fd = inotify_init(); + pollfds[0].events = POLLIN; - if ( fd < 0 ) { + if ( pollfds[0].fd < 0 ) { DPRINTF(E_ERROR, L_INOTIFY, "inotify_init() failed!\n"); } while( scanning ) { + if( quitting ) + goto quitting; sleep(1); } - inotify_create_watches(fd); + inotify_create_watches(pollfds[0].fd); if (setpriority(PRIO_PROCESS, 0, 19) == -1) DPRINTF(E_WARN, L_INOTIFY, "Failed to reduce inotify thread priority\n"); - while( 1 ) + while( !quitting ) { - length = read(fd, buffer, BUF_LEN); - - if ( length < 0 ) { - DPRINTF(E_ERROR, L_INOTIFY, "read failed!\n"); - } + length = poll(pollfds, 1, timeout); + if( !length ) + { + continue; + } + else if( length < 0 ) + { + if( (errno == EINTR) || (errno == EAGAIN) ) + continue; + else + DPRINTF(E_ERROR, L_INOTIFY, "read failed!\n"); + } + else + { + length = read(pollfds[0].fd, buffer, BUF_LEN); + } i = 0; while( i < length ) @@ -639,7 +660,7 @@ start_inotify() (event->mask & IN_MOVED_TO && event->mask & IN_ISDIR) ) { DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n", path_buf, (event->mask & IN_MOVED_TO ? "moved here" : "created")); - inotify_insert_directory(fd, esc_name, path_buf); + inotify_insert_directory(pollfds[0].fd, esc_name, path_buf); } else if ( event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO ) { @@ -654,7 +675,7 @@ start_inotify() if ( event->mask & IN_ISDIR ) { DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n", path_buf, (event->mask & IN_MOVED_FROM ? "moved away" : "deleted")); - inotify_remove_directory(fd, path_buf); + inotify_remove_directory(pollfds[0].fd, path_buf); } else { @@ -667,8 +688,9 @@ start_inotify() i += EVENT_SIZE + event->len; } } - inotify_remove_watches(fd); - close(fd); + inotify_remove_watches(pollfds[0].fd); +quitting: + close(pollfds[0].fd); - return NULL; + return 0; } diff --git a/minidlna.c b/minidlna.c index c92b40d..6f3b200 100644 --- a/minidlna.c +++ b/minidlna.c @@ -56,8 +56,6 @@ # define sqlite3_threadsafe() 0 #endif -static volatile int quitting = 0; - /* OpenAndConfHTTPSocket() : * setup the socket used to handle incoming HTTP connections. */ static int @@ -649,7 +647,8 @@ main(int argc, char * * argv) int last_changecnt = 0; char * sql; short int new_db = 0; - pthread_t thread[2]; + pid_t scanner_pid = 0; + pthread_t inotify_thread = 0; #ifdef TIVO_SUPPORT unsigned short int beacon_interval = 5; int sbeacon = -1; @@ -704,7 +703,8 @@ main(int argc, char * * argv) } if( sql_get_table(db, "pragma user_version", &result, &rows, 0) == SQLITE_OK ) { - if( atoi(result[1]) != DB_VERSION ) { + if( atoi(result[1]) != DB_VERSION ) + { if( new_db ) { DPRINTF(E_WARN, L_GENERAL, "Creating new database...\n"); @@ -722,27 +722,26 @@ main(int argc, char * * argv) { DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database! Exiting...\n"); } +#if USE_FORK scanning = 1; - #if USE_FORK - if( sqlite3_threadsafe() && sqlite3_libversion_number() >= 3005001 ) - { - if( pthread_create(&thread[0], NULL, start_scanner, NULL) ) - { - DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_scanner.\n"); - } - } - else + sqlite3_close(db); + scanner_pid = fork(); + sqlite3_open(DB_PATH "/files.db", &db); + sqlite3_busy_timeout(db, 5000); + if( !scanner_pid ) // child (scanner) process { start_scanner(); + sqlite3_close(db); + exit(EXIT_SUCCESS); } - #else +#else start_scanner(); - #endif +#endif } sqlite3_free_table(result); } if( sqlite3_threadsafe() && sqlite3_libversion_number() >= 3005001 && - GETFLAG(INOTIFYMASK) && pthread_create(&thread[1], NULL, start_inotify, NULL) ) + GETFLAG(INOTIFYMASK) && pthread_create(&inotify_thread, NULL, start_inotify, NULL) ) { DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_inotify.\n"); } @@ -861,6 +860,12 @@ main(int argc, char * * argv) #endif } + if( scanning ) + { + if( !scanner_pid || kill(scanner_pid, 0) ) + scanning = 0; + } + /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */ FD_ZERO(&readset); @@ -981,6 +986,11 @@ main(int argc, char * * argv) } shutdown: + /* kill the scanner */ + if( scanning && scanner_pid ) + { + kill(scanner_pid, 9); + } /* close out open sockets */ while(upnphttphead.lh_first != NULL) { @@ -1002,22 +1012,31 @@ shutdown: for(i=0; ipath); + last_path = media_path; media_path = media_path->next; + free(last_path); } struct album_art_name_s * art_names = album_art_names; + struct album_art_name_s * last_name; while( art_names ) { free(art_names->name); + last_name = art_names; art_names = art_names->next; + free(last_name); } if(unlink(pidfilename) < 0) @@ -1026,7 +1045,7 @@ shutdown: } freeoptions(); - - return 0; + + exit(EXIT_SUCCESS); } diff --git a/scanner.c b/scanner.c index 7ed91c7..a41c064 100644 --- a/scanner.c +++ b/scanner.c @@ -809,7 +809,7 @@ ScanDirectory(const char * dir, const char * parent, enum media_types dir_type) } } -void * +void start_scanner() { struct media_dir_s * media_path = media_dirs; @@ -822,7 +822,6 @@ start_scanner() if( flag ) fclose(flag); #endif - scanning = 1; freopen("/dev/null", "a", stderr); while( media_path ) { @@ -830,7 +829,6 @@ start_scanner() media_path = media_path->next; } freopen("/proc/self/fd/2", "a", stderr); - scanning = 0; #ifdef READYNAS if( access("/ramfs/.rescan_done", F_OK) == 0 ) system("/bin/sh /ramfs/.rescan_done"); @@ -840,6 +838,4 @@ start_scanner() * This index is very useful for large libraries used with an XBox360 (or any * client that uses UPnPSearch on large containers). */ sql_exec(db, "create INDEX IDX_SEARCH_OPT ON OBJECTS(OBJECT_ID, CLASS, DETAIL_ID);"); - - return 0; } diff --git a/scanner.h b/scanner.h index 004592b..36247f7 100644 --- a/scanner.h +++ b/scanner.h @@ -38,7 +38,7 @@ insert_file(char * name, const char * path, const char * parentID, int object); int CreateDatabase(void); -void * +void start_scanner(); #endif diff --git a/tagutils/tagutils.c b/tagutils/tagutils.c index 1cb171e..3251311 100644 --- a/tagutils/tagutils.c +++ b/tagutils/tagutils.c @@ -220,7 +220,7 @@ _make_composite_tags(struct song_metadata *psong) } } - +#if 0 // already taken care of by scanner.c if(!psong->title) { char *suffix; @@ -228,6 +228,7 @@ _make_composite_tags(struct song_metadata *psong) suffix = strrchr(psong->title, '.'); if(suffix) *suffix = '\0'; } +#endif } diff --git a/upnpglobalvars.c b/upnpglobalvars.c index f4150f5..9813b5c 100644 --- a/upnpglobalvars.c +++ b/upnpglobalvars.c @@ -46,4 +46,5 @@ struct media_dir_s * media_dirs = NULL; struct album_art_name_s * album_art_names = NULL; struct client_cache_s clients[CLIENT_CACHE_SLOTS]; short int scanning = 0; +volatile short int quitting = 0; volatile __u32 updateID = 0; diff --git a/upnpglobalvars.h b/upnpglobalvars.h index 4452241..ebbb77c 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -111,6 +111,7 @@ extern struct media_dir_s * media_dirs; extern struct album_art_name_s * album_art_names; extern struct client_cache_s clients[CLIENT_CACHE_SLOTS]; extern short int scanning; +extern volatile short int quitting; extern volatile __u32 updateID; #endif