protect gdbm_* functions from reentrancy
This commit is contained in:
parent
8e09f1f042
commit
cbbddc5750
|
@ -145,12 +145,16 @@ static GDBM_FILE db_songs; /**< Database that holds the mp3 info */
|
||||||
static struct rbtree *db_removed; /**< rbtree to do quick searchs to do background scans */
|
static struct rbtree *db_removed; /**< rbtree to do quick searchs to do background scans */
|
||||||
static MP3FILE gdbm_mp3; /**< used during enumerations */
|
static MP3FILE gdbm_mp3; /**< used during enumerations */
|
||||||
static int gdbm_mp3_mustfree=0; /**< is the data in #gdbm_mp3 valid? Should it be freed? */
|
static int gdbm_mp3_mustfree=0; /**< is the data in #gdbm_mp3 valid? Should it be freed? */
|
||||||
|
static pthread_mutex_t db_gdbm_mutex = PTHREAD_MUTEX_INITIALIZER; /**< gdbm not reentrant */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forwards
|
* Forwards
|
||||||
*/
|
*/
|
||||||
static void db_writelock(void);
|
static void db_writelock(void);
|
||||||
static void db_readlock(void);
|
static void db_readlock(void);
|
||||||
|
static int db_unlock(void);
|
||||||
|
static void db_gdbmlock(void);
|
||||||
|
static int db_gdbmunlock(void);
|
||||||
|
|
||||||
int db_start_initial_update(void);
|
int db_start_initial_update(void);
|
||||||
int db_end_initial_update(void);
|
int db_end_initial_update(void);
|
||||||
|
@ -216,6 +220,29 @@ int db_unlock(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* db_gdbmlock
|
||||||
|
*
|
||||||
|
* lock the gdbm functions
|
||||||
|
*/
|
||||||
|
void db_gdbmlock(void) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if((err=pthread_mutex_lock(&db_gdbm_mutex))) {
|
||||||
|
DPRINTF(E_FATAL,L_DB,"cannot lock gdbmlock: %s\n",strerror(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* db_gdbmunlock
|
||||||
|
*
|
||||||
|
* useless, but symmetrical
|
||||||
|
*/
|
||||||
|
int db_gdbmunlock(void) {
|
||||||
|
return pthread_mutex_unlock(&db_gdbm_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* db_compare_rb_nodes
|
* db_compare_rb_nodes
|
||||||
*
|
*
|
||||||
|
@ -252,8 +279,12 @@ int db_open(char *parameters, int reload) {
|
||||||
snprintf(db_path,sizeof(db_path),"%s/%s",parameters,"songs.gdb");
|
snprintf(db_path,sizeof(db_path),"%s/%s",parameters,"songs.gdb");
|
||||||
|
|
||||||
reload = reload ? GDBM_NEWDB : GDBM_WRCREAT;
|
reload = reload ? GDBM_NEWDB : GDBM_WRCREAT;
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
db_songs=gdbm_open(db_path, 0, reload | GDBM_SYNC | GDBM_NOLOCK,
|
db_songs=gdbm_open(db_path, 0, reload | GDBM_SYNC | GDBM_NOLOCK,
|
||||||
0600,NULL);
|
0600,NULL);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
if(!db_songs) {
|
if(!db_songs) {
|
||||||
DPRINTF(E_FATAL,L_DB,"Could not open songs database (%s)\n",
|
DPRINTF(E_FATAL,L_DB,"Could not open songs database (%s)\n",
|
||||||
db_path);
|
db_path);
|
||||||
|
@ -282,13 +313,18 @@ int db_init(void) {
|
||||||
DPRINTF(E_DBG,L_DB|L_PL,"Building playlists\n");
|
DPRINTF(E_DBG,L_DB|L_PL,"Building playlists\n");
|
||||||
|
|
||||||
/* count the actual songs and build the playlists */
|
/* count the actual songs and build the playlists */
|
||||||
|
db_gdbmlock();
|
||||||
tmp_key=gdbm_firstkey(db_songs);
|
tmp_key=gdbm_firstkey(db_songs);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
MEMNOTIFY(tmp_key.dptr);
|
MEMNOTIFY(tmp_key.dptr);
|
||||||
|
|
||||||
while(tmp_key.dptr) {
|
while(tmp_key.dptr) {
|
||||||
/* Fetch that key */
|
/* Fetch that key */
|
||||||
|
db_gdbmlock();
|
||||||
song_data=gdbm_fetch(db_songs,tmp_key);
|
song_data=gdbm_fetch(db_songs,tmp_key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
MEMNOTIFY(song_data.dptr);
|
MEMNOTIFY(song_data.dptr);
|
||||||
if(song_data.dptr) {
|
if(song_data.dptr) {
|
||||||
if(!db_unpackrecord(&song_data,&mp3file)) {
|
if(!db_unpackrecord(&song_data,&mp3file)) {
|
||||||
|
@ -299,7 +335,10 @@ int db_init(void) {
|
||||||
free(song_data.dptr);
|
free(song_data.dptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
tmp_nextkey=gdbm_nextkey(db_songs,tmp_key);
|
tmp_nextkey=gdbm_nextkey(db_songs,tmp_key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
MEMNOTIFY(tmp_nextkey.dptr);
|
MEMNOTIFY(tmp_nextkey.dptr);
|
||||||
free(tmp_key.dptr);
|
free(tmp_key.dptr);
|
||||||
tmp_key=tmp_nextkey;
|
tmp_key=tmp_nextkey;
|
||||||
|
@ -321,7 +360,9 @@ int db_deinit(void) {
|
||||||
DB_PLAYLIST *plist;
|
DB_PLAYLIST *plist;
|
||||||
DB_PLAYLISTENTRY *pentry;
|
DB_PLAYLISTENTRY *pentry;
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
gdbm_close(db_songs);
|
gdbm_close(db_songs);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
while(db_playlists.next) {
|
while(db_playlists.next) {
|
||||||
plist=db_playlists.next;
|
plist=db_playlists.next;
|
||||||
|
@ -383,7 +424,9 @@ int db_start_initial_update(void) {
|
||||||
|
|
||||||
/* load up the red-black tree with all the current songs in the db */
|
/* load up the red-black tree with all the current songs in the db */
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
tmp_key=gdbm_firstkey(db_songs);
|
tmp_key=gdbm_firstkey(db_songs);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
MEMNOTIFY(tmp_key.dptr);
|
MEMNOTIFY(tmp_key.dptr);
|
||||||
|
|
||||||
|
@ -395,7 +438,10 @@ int db_start_initial_update(void) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
tmp_nextkey=gdbm_nextkey(db_songs,tmp_key);
|
tmp_nextkey=gdbm_nextkey(db_songs,tmp_key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
MEMNOTIFY(tmp_nextkey.dptr);
|
MEMNOTIFY(tmp_nextkey.dptr);
|
||||||
// free(tmp_key.dptr); /* we'll free it in update mode */
|
// free(tmp_key.dptr); /* we'll free it in update mode */
|
||||||
tmp_key=tmp_nextkey;
|
tmp_key=tmp_nextkey;
|
||||||
|
@ -428,10 +474,12 @@ int db_end_initial_update(void) {
|
||||||
DPRINTF(E_DBG,L_DB,"Reorganizing db\n");
|
DPRINTF(E_DBG,L_DB,"Reorganizing db\n");
|
||||||
|
|
||||||
db_writelock();
|
db_writelock();
|
||||||
|
db_gdbmlock();
|
||||||
gdbm_reorganize(db_songs);
|
gdbm_reorganize(db_songs);
|
||||||
gdbm_sync(db_songs);
|
gdbm_sync(db_songs);
|
||||||
DPRINTF(E_DBG,L_DB,"Reorganize done\n");
|
DPRINTF(E_DBG,L_DB,"Reorganize done\n");
|
||||||
db_update_mode=0;
|
db_update_mode=0;
|
||||||
|
db_gdbmunlock();
|
||||||
db_unlock();
|
db_unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -808,18 +856,24 @@ int db_add(MP3FILE *pmp3) {
|
||||||
|
|
||||||
db_writelock();
|
db_writelock();
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
if(gdbm_store(db_songs,dkey,*pnew,GDBM_REPLACE)) {
|
if(gdbm_store(db_songs,dkey,*pnew,GDBM_REPLACE)) {
|
||||||
|
db_gdbmunlock();
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
DPRINTF(E_DBG,L_DB,"Testing for %d\n",pmp3->id);
|
DPRINTF(E_DBG,L_DB,"Testing for %d\n",pmp3->id);
|
||||||
id=pmp3->id;
|
id=pmp3->id;
|
||||||
dkey.dptr=(void*)&id;
|
dkey.dptr=(void*)&id;
|
||||||
dkey.dsize=sizeof(unsigned int);
|
dkey.dsize=sizeof(unsigned int);
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
if(!gdbm_exists(db_songs,dkey)) {
|
if(!gdbm_exists(db_songs,dkey)) {
|
||||||
|
db_gdbmunlock();
|
||||||
DPRINTF(E_FATAL,L_DB,"Error.. could not find just added file\n");
|
DPRINTF(E_FATAL,L_DB,"Error.. could not find just added file\n");
|
||||||
}
|
}
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
free(pnew->dptr);
|
free(pnew->dptr);
|
||||||
free(pnew);
|
free(pnew);
|
||||||
|
@ -915,6 +969,7 @@ ENUMHANDLE db_enum_begin(void) {
|
||||||
|
|
||||||
helper = calloc(1, sizeof(MP3HELPER));
|
helper = calloc(1, sizeof(MP3HELPER));
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
for(key = gdbm_firstkey(db_songs) ; key.dptr ; key = next)
|
for(key = gdbm_firstkey(db_songs) ; key.dptr ; key = next)
|
||||||
{
|
{
|
||||||
MP3RECORD* entry = calloc(1, sizeof(MP3RECORD));
|
MP3RECORD* entry = calloc(1, sizeof(MP3RECORD));
|
||||||
|
@ -941,6 +996,7 @@ ENUMHANDLE db_enum_begin(void) {
|
||||||
free(key.dptr);
|
free(key.dptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_gdbm_unlock();
|
||||||
db_unlock();
|
db_unlock();
|
||||||
helper->next = helper->root;
|
helper->next = helper->root;
|
||||||
|
|
||||||
|
@ -1010,7 +1066,9 @@ ENUMHANDLE db_enum_begin(void) {
|
||||||
}
|
}
|
||||||
gdbm_mp3_mustfree=0;
|
gdbm_mp3_mustfree=0;
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
*pkey=gdbm_firstkey(db_songs);
|
*pkey=gdbm_firstkey(db_songs);
|
||||||
|
db_gdbmunlock();
|
||||||
return (ENUMHANDLE)pkey;
|
return (ENUMHANDLE)pkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,7 +1083,10 @@ MP3FILE *db_enum(ENUMHANDLE *current) {
|
||||||
gdbm_mp3_mustfree=0;
|
gdbm_mp3_mustfree=0;
|
||||||
|
|
||||||
if(pkey->dptr) {
|
if(pkey->dptr) {
|
||||||
|
db_gdbmlock();
|
||||||
data=gdbm_fetch(db_songs,*pkey);
|
data=gdbm_fetch(db_songs,*pkey);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
if(!data.dptr)
|
if(!data.dptr)
|
||||||
DPRINTF(E_FATAL,L_DB, "Cannot find item.... corrupt database?\n");
|
DPRINTF(E_FATAL,L_DB, "Cannot find item.... corrupt database?\n");
|
||||||
|
|
||||||
|
@ -1035,7 +1096,10 @@ MP3FILE *db_enum(ENUMHANDLE *current) {
|
||||||
|
|
||||||
free(data.dptr);
|
free(data.dptr);
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
next = gdbm_nextkey(db_songs,*pkey);
|
next = gdbm_nextkey(db_songs,*pkey);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
free(pkey->dptr);
|
free(pkey->dptr);
|
||||||
*pkey=next;
|
*pkey=next;
|
||||||
|
|
||||||
|
@ -1184,7 +1248,10 @@ MP3FILE *db_find(int id) { /* FIXME: Not reentrant */
|
||||||
|
|
||||||
db_readlock();
|
db_readlock();
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
content=gdbm_fetch(db_songs,key);
|
content=gdbm_fetch(db_songs,key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1332,7 +1399,10 @@ int db_exists(int id) {
|
||||||
|
|
||||||
db_readlock();
|
db_readlock();
|
||||||
|
|
||||||
|
db_gdbmlock();
|
||||||
content=gdbm_fetch(db_songs,key);
|
content=gdbm_fetch(db_songs,key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
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");
|
||||||
|
@ -1401,7 +1471,10 @@ int db_delete(int id) {
|
||||||
db_writelock();
|
db_writelock();
|
||||||
key.dptr=(void*)&id;
|
key.dptr=(void*)&id;
|
||||||
key.dsize=sizeof(int);
|
key.dsize=sizeof(int);
|
||||||
|
db_gdbmlock();
|
||||||
gdbm_delete(db_songs,key);
|
gdbm_delete(db_songs,key);
|
||||||
|
db_gdbmunlock();
|
||||||
|
|
||||||
db_song_count--;
|
db_song_count--;
|
||||||
db_version_no++;
|
db_version_no++;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue