mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-23 12:43:18 -05:00
Add per-thread db handles to guard against SQLITE_MISUSE
This commit is contained in:
parent
6df87878a5
commit
43c234e666
@ -62,11 +62,11 @@
|
||||
|
||||
|
||||
/* Globals */
|
||||
static sqlite *db_sqlite2_songs; /**< Database that holds the mp3 info */
|
||||
static pthread_mutex_t db_sqlite2_mutex = PTHREAD_MUTEX_INITIALIZER; /**< sqlite not reentrant */
|
||||
static sqlite_vm *db_sqlite2_pvm;
|
||||
static int db_sqlite2_reload=0;
|
||||
static char *db_sqlite2_enum_query;
|
||||
static pthread_key_t db_sqlite2_key;
|
||||
|
||||
static char db_sqlite2_path[PATH_MAX + 1];
|
||||
|
||||
@ -80,6 +80,38 @@ extern char *db_sqlite2_initial1;
|
||||
extern char *db_sqlite2_initial2;
|
||||
int db_sqlite2_enum_begin_helper(char **pe);
|
||||
|
||||
/**
|
||||
* get (or create) the db handle
|
||||
*/
|
||||
sqlite *db_sqlite2_handle(void) {
|
||||
sqlite *pdb = NULL;
|
||||
char *perr;
|
||||
char *pe = NULL;
|
||||
|
||||
pdb = (sqlite *)pthread_getspecific(db_sqlite2_key);
|
||||
if(pdb == NULL) { /* don't have a handle yet */
|
||||
if((pdb = sqlite_open(db_sqlite2_path,0666,&perr)) == NULL) {
|
||||
db_get_error(&pe,DB_E_SQL_ERROR,perr);
|
||||
DPRINTF(E_FATAL,L_DB,"db_sqlite2_open: %s (%s)\n",perr,
|
||||
db_sqlite2_path);
|
||||
sqlite_freemem(perr);
|
||||
db_sqlite2_unlock();
|
||||
return NULL;
|
||||
}
|
||||
sqlite_busy_timeout(pdb,30000); /* 30 seconds */
|
||||
pthread_setspecific(db_sqlite2_key,(void*)pdb);
|
||||
}
|
||||
|
||||
return pdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* free a thread-specific db handle
|
||||
*/
|
||||
void db_sqlite2_freedb(sqlite *pdb) {
|
||||
sqlite_close(pdb);
|
||||
}
|
||||
|
||||
/**
|
||||
* lock the db_mutex
|
||||
*/
|
||||
@ -130,15 +162,17 @@ void db_sqlite2_vmfree(char *query) {
|
||||
* @returns DB_E_SUCCESS on success
|
||||
*/
|
||||
int db_sqlite2_open(char **pe, char *dsn) {
|
||||
sqlite *pdb;
|
||||
char *perr;
|
||||
int ver;
|
||||
int err;
|
||||
|
||||
pthread_key_create(&db_sqlite2_key, (void*)db_sqlite2_freedb);
|
||||
snprintf(db_sqlite2_path,sizeof(db_sqlite2_path),"%s/songs.db",dsn);
|
||||
|
||||
db_sqlite2_lock();
|
||||
db_sqlite2_songs=sqlite_open(db_sqlite2_path,0666,&perr);
|
||||
if(!db_sqlite2_songs) {
|
||||
pdb=sqlite_open(db_sqlite2_path,0666,&perr);
|
||||
if(!pdb) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,perr);
|
||||
DPRINTF(E_LOG,L_DB,"db_sqlite2_open: %s (%s)\n",perr,
|
||||
db_sqlite2_path);
|
||||
@ -146,8 +180,7 @@ int db_sqlite2_open(char **pe, char *dsn) {
|
||||
db_sqlite2_unlock();
|
||||
return DB_E_SQL_ERROR;
|
||||
}
|
||||
|
||||
sqlite_busy_timeout(db_sqlite2_songs,30000); /* 30 seconds */
|
||||
sqlite_close(pdb);
|
||||
db_sqlite2_unlock();
|
||||
|
||||
err = db_sql_fetch_int(pe,&ver,"select value from config where "
|
||||
@ -176,9 +209,6 @@ int db_sqlite2_open(char **pe, char *dsn) {
|
||||
* close the database
|
||||
*/
|
||||
int db_sqlite2_close(void) {
|
||||
db_sqlite2_lock();
|
||||
sqlite_close(db_sqlite2_songs);
|
||||
db_sqlite2_unlock();
|
||||
return DB_E_SUCCESS;
|
||||
}
|
||||
|
||||
@ -205,7 +235,7 @@ int db_sqlite2_exec(char **pe, int loglevel, char *fmt, ...) {
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",query);
|
||||
|
||||
db_sqlite2_lock();
|
||||
err=sqlite_exec(db_sqlite2_songs,query,NULL,NULL,&perr);
|
||||
err=sqlite_exec(db_sqlite2_handle(),query,NULL,NULL,&perr);
|
||||
if(err != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,perr);
|
||||
|
||||
@ -214,7 +244,7 @@ int db_sqlite2_exec(char **pe, int loglevel, char *fmt, ...) {
|
||||
DPRINTF(loglevel,L_DB,"Error: %s\n",perr);
|
||||
sqlite_freemem(perr);
|
||||
} else {
|
||||
DPRINTF(E_DBG,L_DB,"Rows: %d\n",sqlite_changes(db_sqlite2_songs));
|
||||
DPRINTF(E_DBG,L_DB,"Rows: %d\n",sqlite_changes(db_sqlite2_handle()));
|
||||
}
|
||||
sqlite_freemem(query);
|
||||
|
||||
@ -246,7 +276,7 @@ int db_sqlite2_enum_begin_helper(char **pe) {
|
||||
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",db_sqlite2_enum_query);
|
||||
|
||||
err=sqlite_compile(db_sqlite2_songs,db_sqlite2_enum_query,
|
||||
err=sqlite_compile(db_sqlite2_handle(),db_sqlite2_enum_query,
|
||||
&ptail,&db_sqlite2_pvm,&perr);
|
||||
|
||||
if(err != SQLITE_OK) {
|
||||
@ -430,7 +460,7 @@ int db_sqlite2_event(int event_type) {
|
||||
*/
|
||||
|
||||
int db_sqlite2_insert_id(void) {
|
||||
return sqlite_last_insert_rowid(db_sqlite2_songs);
|
||||
return sqlite_last_insert_rowid(db_sqlite2_handle());
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,7 +62,6 @@
|
||||
|
||||
|
||||
/* Globals */
|
||||
static sqlite3 *db_sqlite3_songs; /**< Database that holds the mp3 info */
|
||||
static pthread_mutex_t db_sqlite3_mutex = PTHREAD_MUTEX_INITIALIZER; /**< sqlite not reentrant */
|
||||
static sqlite3_stmt *db_sqlite3_stmt;
|
||||
static const char *db_sqlite3_ptail;
|
||||
@ -70,7 +69,7 @@ static int db_sqlite3_finalized;
|
||||
static int db_sqlite3_reload=0;
|
||||
static char *db_sqlite3_enum_query=NULL;
|
||||
static char **db_sqlite3_row = NULL;
|
||||
|
||||
static pthread_key_t db_sqlite3_key;
|
||||
static char db_sqlite3_path[PATH_MAX + 1];
|
||||
|
||||
#define DB_SQLITE3_VERSION 13
|
||||
@ -85,6 +84,36 @@ int db_sqlite3_enum_begin_helper(char **pe);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* get (or create) the db handle
|
||||
*/
|
||||
sqlite3 *db_sqlite3_handle(void) {
|
||||
sqlite3 *pdb = NULL;
|
||||
char *pe = NULL;
|
||||
|
||||
pdb = (sqlite3*)pthread_getspecific(db_sqlite3_key);
|
||||
if(pdb == NULL) { /* don't have a handle yet */
|
||||
DPRINTF(E_DBG,L_DB,"Creating new db handle\n");
|
||||
if(sqlite3_open(db_sqlite3_path,&pdb) != SQLITE_OK) {
|
||||
db_get_error(&pe,DB_E_SQL_ERROR,sqlite3_errmsg(pdb));
|
||||
DPRINTF(E_FATAL,L_DB,"db_sqlite3_open: %s (%s)\n",pe,db_sqlite3_path);
|
||||
db_sqlite3_unlock();
|
||||
return NULL;
|
||||
}
|
||||
sqlite3_busy_timeout(pdb,30000); /* 30 seconds */
|
||||
pthread_setspecific(db_sqlite3_key,(void*)pdb);
|
||||
}
|
||||
|
||||
return pdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* free a thread-specific db handle
|
||||
*/
|
||||
void db_sqlite3_freedb(sqlite3 *pdb) {
|
||||
sqlite3_close(pdb);
|
||||
}
|
||||
|
||||
/**
|
||||
* lock the db_mutex
|
||||
*/
|
||||
@ -133,19 +162,20 @@ void db_sqlite3_vmfree(char *query) {
|
||||
int db_sqlite3_open(char **pe, char *dsn) {
|
||||
int ver;
|
||||
int err;
|
||||
sqlite3 *pdb;
|
||||
|
||||
pthread_key_create(&db_sqlite3_key, (void*)db_sqlite3_freedb);
|
||||
snprintf(db_sqlite3_path,sizeof(db_sqlite3_path),"%s/songs3.db",dsn);
|
||||
|
||||
db_sqlite3_lock();
|
||||
if(sqlite3_open(db_sqlite3_path,&db_sqlite3_songs) != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_songs));
|
||||
if(sqlite3_open(db_sqlite3_path,&pdb) != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(pdb));
|
||||
DPRINTF(E_LOG,L_DB,"db_sqlite3_open: %s (%s)\n",pe ? *pe : "Unknown",
|
||||
db_sqlite3_path);
|
||||
db_sqlite3_unlock();
|
||||
return DB_E_SQL_ERROR;
|
||||
}
|
||||
|
||||
sqlite3_busy_timeout(db_sqlite3_songs,30000); /* 30 seconds */
|
||||
sqlite3_close(pdb);
|
||||
db_sqlite3_unlock();
|
||||
|
||||
err = db_sql_fetch_int(pe,&ver,"select value from config where "
|
||||
@ -171,9 +201,7 @@ int db_sqlite3_open(char **pe, char *dsn) {
|
||||
* close the database
|
||||
*/
|
||||
int db_sqlite3_close(void) {
|
||||
db_sqlite3_lock();
|
||||
sqlite3_close(db_sqlite3_songs);
|
||||
db_sqlite3_unlock();
|
||||
/* this doens't actually make much sense, as the closes get done by the threads */
|
||||
return DB_E_SUCCESS;
|
||||
}
|
||||
|
||||
@ -201,7 +229,7 @@ int db_sqlite3_exec(char **pe, int loglevel, char *fmt, ...) {
|
||||
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",query);
|
||||
|
||||
err=sqlite3_exec(db_sqlite3_songs,query,NULL,NULL,&perr);
|
||||
err=sqlite3_exec(db_sqlite3_handle(),query,NULL,NULL,&perr);
|
||||
if(err != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,perr);
|
||||
|
||||
@ -210,7 +238,7 @@ int db_sqlite3_exec(char **pe, int loglevel, char *fmt, ...) {
|
||||
DPRINTF(loglevel,L_DB,"Error: %s\n",perr);
|
||||
sqlite3_free(perr);
|
||||
} else {
|
||||
DPRINTF(E_DBG,L_DB,"Rows: %d\n",sqlite3_changes(db_sqlite3_songs));
|
||||
DPRINTF(E_DBG,L_DB,"Rows: %d\n",sqlite3_changes(db_sqlite3_handle()));
|
||||
}
|
||||
sqlite3_free(query);
|
||||
|
||||
@ -243,11 +271,11 @@ int db_sqlite3_enum_begin_helper(char **pe) {
|
||||
*((int*)NULL) = 1;
|
||||
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",db_sqlite3_enum_query);
|
||||
err=sqlite3_prepare(db_sqlite3_songs,db_sqlite3_enum_query,-1,
|
||||
err=sqlite3_prepare(db_sqlite3_handle(),db_sqlite3_enum_query,-1,
|
||||
&db_sqlite3_stmt,&db_sqlite3_ptail);
|
||||
|
||||
if(err != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_songs));
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_handle()));
|
||||
sqlite3_free(db_sqlite3_enum_query);
|
||||
db_sqlite3_enum_query=NULL;
|
||||
db_sqlite3_unlock();
|
||||
@ -325,7 +353,7 @@ int db_sqlite3_enum_fetch(char **pe, SQL_ROW *pr) {
|
||||
free(db_sqlite3_row);
|
||||
db_sqlite3_row = NULL;
|
||||
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_songs));
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_handle()));
|
||||
DPRINTF(E_SPAM,L_DB,"Finalizing statement: %08X\n",db_sqlite3_stmt);
|
||||
sqlite3_finalize(db_sqlite3_stmt);
|
||||
db_sqlite3_finalized=1;
|
||||
@ -352,7 +380,7 @@ int db_sqlite3_enum_end(char **pe) {
|
||||
DPRINTF(E_SPAM,L_DB,"Finalizing statement: %08X\n",db_sqlite3_stmt);
|
||||
err = sqlite3_finalize(db_sqlite3_stmt);
|
||||
if(err != SQLITE_OK) {
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_songs));
|
||||
db_get_error(pe,DB_E_SQL_ERROR,sqlite3_errmsg(db_sqlite3_handle()));
|
||||
db_sqlite3_unlock();
|
||||
return DB_E_SQL_ERROR;
|
||||
}
|
||||
@ -472,7 +500,7 @@ int db_sqlite3_insert_id(void) {
|
||||
int result;
|
||||
|
||||
db_sqlite3_lock();
|
||||
result = (int)sqlite3_last_insert_rowid(db_sqlite3_songs);
|
||||
result = (int)sqlite3_last_insert_rowid(db_sqlite3_handle());
|
||||
db_sqlite3_unlock();
|
||||
|
||||
return result;
|
||||
|
@ -273,7 +273,7 @@ void rsp_info(WS_CONNINFO *pwsc, PRIVINFO *ppi) {
|
||||
|
||||
/* info block */
|
||||
xml_push(pxml,"info");
|
||||
xml_output(pxml,"count","%d",pi_db_count());
|
||||
xml_output(pxml,"count","%d",pi_db_count_items(COUNT_SONGS));
|
||||
xml_output(pxml,"rsp-version","%s",RSP_VERSION);
|
||||
|
||||
xml_output(pxml,"server-version","%s",pi_server_ver());
|
||||
|
Loading…
x
Reference in New Issue
Block a user