Fix race in db_find/db_exists

This commit is contained in:
Ron Pedde 2004-11-16 05:30:44 +00:00
parent b6876538f3
commit 2fa6a01019
1 changed files with 32 additions and 17 deletions

View File

@ -375,6 +375,7 @@ int db_start_initial_update(void) {
if((db_removed=rbinit(db_compare_rb_nodes,NULL)) == NULL) { if((db_removed=rbinit(db_compare_rb_nodes,NULL)) == NULL) {
errno=ENOMEM; errno=ENOMEM;
db_unlock();
return -1; return -1;
} }
@ -388,6 +389,7 @@ int db_start_initial_update(void) {
/* Add it to the rbtree */ /* Add it to the rbtree */
if(!rbsearch((void*)tmp_key.dptr,db_removed)) { if(!rbsearch((void*)tmp_key.dptr,db_removed)) {
errno=ENOMEM; errno=ENOMEM;
db_unlock();
return -1; return -1;
} }
@ -398,6 +400,7 @@ int db_start_initial_update(void) {
} }
db_update_mode=1; db_update_mode=1;
db_unlock();
return 0; return 0;
} }
@ -410,6 +413,7 @@ int db_start_initial_update(void) {
int db_end_initial_update(void) { int db_end_initial_update(void) {
const void *val; const void *val;
db_writelock();
db_update_mode=0; db_update_mode=0;
DPRINTF(E_DBG,L_DB|L_SCAN,"Initial update over. Removing stale items\n"); DPRINTF(E_DBG,L_DB|L_SCAN,"Initial update over. Removing stale items\n");
@ -472,12 +476,15 @@ int db_add_playlist(unsigned int playlistid, char *name, int is_smart) {
DPRINTF(E_DBG,L_DB|L_PL,"Adding new playlist %s\n",name); DPRINTF(E_DBG,L_DB|L_PL,"Adding new playlist %s\n",name);
db_writelock();
pnew->next=db_playlists.next; pnew->next=db_playlists.next;
db_playlists.next=pnew; db_playlists.next=pnew;
db_version_no++; db_version_no++;
DPRINTF(E_DBG,L_DB|L_PL,"Added playlist\n"); DPRINTF(E_DBG,L_DB|L_PL,"Added playlist\n");
db_unlock();
return 0; return 0;
} }
@ -503,14 +510,14 @@ int db_add_playlist_song(unsigned int playlistid, unsigned int itemid) {
DPRINTF(E_DBG,L_DB|L_PL,"Adding item %d to %d\n",itemid,playlistid); DPRINTF(E_DBG,L_DB|L_PL,"Adding item %d to %d\n",itemid,playlistid);
db_writelock();
current=db_playlists.next; current=db_playlists.next;
while(current && (current->id != playlistid)) while(current && (current->id != playlistid))
current=current->next; current=current->next;
if(!current) { if(!current) {
DPRINTF(E_WARN,L_DB|L_PL,"Could not find playlist attempting to add to\n"); DPRINTF(E_WARN,L_DB|L_PL,"Could not find playlist attempting to add to\n");
if(!db_update_mode)
db_unlock();
db_unlock(); db_unlock();
free(pnew); free(pnew);
return -1; return -1;
@ -527,6 +534,8 @@ int db_add_playlist_song(unsigned int playlistid, unsigned int itemid) {
db_version_no++; db_version_no++;
DPRINTF(E_DBG,L_DB|L_PL,"Added playlist item\n"); DPRINTF(E_DBG,L_DB|L_PL,"Added playlist item\n");
db_unlock();
return 0; return 0;
} }
@ -795,6 +804,8 @@ int db_add(MP3FILE *pmp3) {
ppacked->time_modified=(int)time(NULL); ppacked->time_modified=(int)time(NULL);
ppacked->time_played=0; /* do we want to keep track of this? */ ppacked->time_played=0; /* do we want to keep track of this? */
db_writelock();
if(gdbm_store(db_songs,dkey,*pnew,GDBM_REPLACE)) { if(gdbm_store(db_songs,dkey,*pnew,GDBM_REPLACE)) {
DPRINTF(E_FATAL,L_DB,"Error inserting file %s in database\n",pmp3->fname); DPRINTF(E_FATAL,L_DB,"Error inserting file %s in database\n",pmp3->fname);
} }
@ -816,6 +827,8 @@ int db_add(MP3FILE *pmp3) {
db_song_count++; db_song_count++;
DPRINTF(E_DBG,L_DB,"Added file\n"); DPRINTF(E_DBG,L_DB,"Added file\n");
db_unlock();
return 0; return 0;
} }
@ -1168,16 +1181,12 @@ MP3FILE *db_find(int id) { /* FIXME: Not reentrant */
key.dptr=(char*)&id; key.dptr=(char*)&id;
key.dsize=sizeof(int); key.dsize=sizeof(int);
if(!db_update_mode) { db_readlock();
db_readlock(); /** \todo fix race */
is_locked=1;
}
content=gdbm_fetch(db_songs,key); content=gdbm_fetch(db_songs,key);
MEMNOTIFY(content.dptr); MEMNOTIFY(content.dptr);
if(!content.dptr) { if(!content.dptr) {
DPRINTF(E_WARN,L_DB,"Could not find id %d\n",id); DPRINTF(E_WARN,L_DB,"Could not find id %d\n",id);
if(is_locked)
db_unlock(); db_unlock();
return NULL; return NULL;
} }
@ -1185,14 +1194,12 @@ MP3FILE *db_find(int id) { /* FIXME: Not reentrant */
pmp3=(MP3FILE*)malloc(sizeof(MP3FILE)); pmp3=(MP3FILE*)malloc(sizeof(MP3FILE));
if(!pmp3) { if(!pmp3) {
DPRINTF(E_LOG,L_MISC,"Malloc failed in db_find\n"); DPRINTF(E_LOG,L_MISC,"Malloc failed in db_find\n");
if(is_locked)
db_unlock(); db_unlock();
return NULL; return NULL;
} }
db_unpackrecord(&content,pmp3); db_unpackrecord(&content,pmp3);
free(content.dptr); free(content.dptr);
if(is_locked)
db_unlock(); db_unlock();
return pmp3; return pmp3;
} }
@ -1313,10 +1320,13 @@ int db_exists(int id) {
key.dptr=(char*)&id; key.dptr=(char*)&id;
key.dsize=sizeof(int); key.dsize=sizeof(int);
db_readlock();
content=gdbm_fetch(db_songs,key); content=gdbm_fetch(db_songs,key);
MEMNOTIFY(content.dptr); MEMNOTIFY(content.dptr);
if(!content.dptr) { if(!content.dptr) {
DPRINTF(E_DBG,L_DB,"Nope! Not in DB\n"); DPRINTF(E_DBG,L_DB,"Nope! Not in DB\n");
db_unlock();
return 0; return 0;
} }
@ -1329,6 +1339,8 @@ int db_exists(int id) {
} }
} }
db_unlock();
free(content.dptr); free(content.dptr);
DPRINTF(E_DBG,L_DB,"Yup, in database\n"); DPRINTF(E_DBG,L_DB,"Yup, in database\n");
return 1; return 1;
@ -1345,6 +1357,7 @@ int db_last_modified(int id) {
MP3FILE *pmp3; MP3FILE *pmp3;
int err; int err;
/* readlocked as part of db_find */
pmp3=db_find(id); pmp3=db_find(id);
if(!pmp3) { if(!pmp3) {
retval=0; retval=0;
@ -1375,6 +1388,7 @@ int db_delete(int id) {
DPRINTF(E_DBG,L_DB,"Removing item %d\n",id); DPRINTF(E_DBG,L_DB,"Removing item %d\n",id);
if(db_exists(id)) { if(db_exists(id)) {
db_writelock();
key.dptr=(void*)&id; key.dptr=(void*)&id;
key.dsize=sizeof(int); key.dsize=sizeof(int);
gdbm_delete(db_songs,key); gdbm_delete(db_songs,key);
@ -1407,9 +1421,10 @@ int db_delete(int id) {
} }
pcurrent=pcurrent->next; pcurrent=pcurrent->next;
} }
db_version_no++;
db_unlock();
} }
db_version_no++;
return 0; return 0;
} }