Skip to content

Commit 80a52ea

Browse files
authored
Merge pull request #2847 from pi-hole/fix/api_parallelism
Improve thread-safety for concurrent API requests
2 parents 3a03bd7 + abda470 commit 80a52ea

6 files changed

Lines changed: 34 additions & 24 deletions

File tree

src/api/2fa.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ int generateTOTP(struct ftl_conn *api)
283283
// Create JSON object
284284
cJSON *tjson = cJSON_CreateObject();
285285
JSON_REF_STR_IN_OBJECT(tjson, "type", "totp");
286-
JSON_REF_STR_IN_OBJECT(tjson, "account", config.webserver.domain.v.s);
286+
JSON_COPY_STR_TO_OBJECT(tjson, "account", config.webserver.domain.v.s);
287287
JSON_REF_STR_IN_OBJECT(tjson, "issuer", "Pi-hole%20API");
288288
JSON_REF_STR_IN_OBJECT(tjson, "algorithm", "SHA1");
289289
JSON_ADD_NUMBER_TO_OBJECT(tjson, "digits", RFC6238_DIGITS);

src/api/config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ cJSON *addJSONConfValue(const enum conf_type conf_type, union conf_value *val)
111111
return cJSON_CreateNumber(val->d);
112112
case CONF_STRING:
113113
case CONF_STRING_ALLOCATED:
114-
return val->s ? cJSON_CreateStringReference(val->s) : cJSON_CreateNull();
114+
return val->s ? cJSON_CreateString(val->s) : cJSON_CreateNull();
115115
case CONF_ENUM_PTR_TYPE:
116116
return cJSON_CreateStringReference(get_ptr_type_str(val->ptr_type));
117117
case CONF_ENUM_BUSY_TYPE:

src/api/list.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ static int api_list_read(struct ftl_conn *api,
3030
cJSON *processed)
3131
{
3232
const char *sql_msg = NULL;
33-
if(!gravityDB_readTable(listtype, item, &sql_msg, true, NULL))
33+
sqlite3_stmt *stmt = NULL;
34+
if(!gravityDB_readTable(listtype, item, &sql_msg, true, NULL, &stmt))
3435
{
3536
return send_json_error(api, 400, // 400 Bad Request
3637
"database_error",
@@ -40,7 +41,7 @@ static int api_list_read(struct ftl_conn *api,
4041

4142
tablerow table = { 0 };
4243
cJSON *rows = JSON_NEW_ARRAY();
43-
while(gravityDB_readTableGetRow(listtype, &table, &sql_msg))
44+
while(gravityDB_readTableGetRow(listtype, &table, &sql_msg, stmt))
4445
{
4546
cJSON *row = JSON_NEW_OBJECT();
4647

@@ -98,7 +99,7 @@ static int api_list_read(struct ftl_conn *api,
9899
if(ret != 0)
99100
{
100101
JSON_DELETE(rows);
101-
gravityDB_readTableFinalize();
102+
gravityDB_readTableFinalize(stmt);
102103
return ret;
103104
}
104105

@@ -135,7 +136,7 @@ static int api_list_read(struct ftl_conn *api,
135136

136137
JSON_ADD_ITEM_TO_ARRAY(rows, row);
137138
}
138-
gravityDB_readTableFinalize();
139+
gravityDB_readTableFinalize(stmt);
139140

140141
if(sql_msg == NULL)
141142
{

src/api/search.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ static int search_table(struct ftl_conn *api, const char *item,
3838

3939
// Check domain against lists table
4040
const char *sql_msg = NULL;
41-
if(!gravityDB_readTable(listtype, item, &sql_msg, !partial, ids))
41+
sqlite3_stmt *stmt = NULL;
42+
if(!gravityDB_readTable(listtype, item, &sql_msg, !partial, ids, &stmt))
4243
{
4344
return send_json_error(api, 400, // 400 Bad Request
4445
"database_error",
@@ -47,7 +48,7 @@ static int search_table(struct ftl_conn *api, const char *item,
4748
}
4849

4950
tablerow table;
50-
while(gravityDB_readTableGetRow(listtype, &table, &sql_msg))
51+
while(gravityDB_readTableGetRow(listtype, &table, &sql_msg, stmt))
5152
{
5253
if(++(*N) > limit)
5354
continue;
@@ -83,7 +84,7 @@ static int search_table(struct ftl_conn *api, const char *item,
8384
const int ret = parse_groupIDs(api, &table, row);
8485
if(ret != 0)
8586
{
86-
gravityDB_readTableFinalize();
87+
gravityDB_readTableFinalize(stmt);
8788
return ret;
8889
}
8990
}
@@ -95,7 +96,7 @@ static int search_table(struct ftl_conn *api, const char *item,
9596
}
9697
JSON_ADD_ITEM_TO_ARRAY(json, row);
9798
}
98-
gravityDB_readTableFinalize();
99+
gravityDB_readTableFinalize(stmt);
99100

100101
return 200;
101102
}

src/database/gravity-db.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,10 +2049,10 @@ bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON*
20492049
return true;
20502050
}
20512051

2052-
static sqlite3_stmt* read_stmt = NULL;
20532052
bool gravityDB_readTable(const enum gravity_list_type listtype,
20542053
const char *item, const char **message,
2055-
const bool exact, const char *ids)
2054+
const bool exact, const char *ids,
2055+
sqlite3_stmt **read_stmt_p)
20562056
{
20572057
if(gravity_db == NULL)
20582058
{
@@ -2208,7 +2208,8 @@ bool gravityDB_readTable(const enum gravity_list_type listtype,
22082208
}
22092209

22102210
// Prepare SQLite statement
2211-
int rc = sqlite3_prepare_v2(gravity_db, querystr, -1, &read_stmt, NULL);
2211+
*read_stmt_p = NULL;
2212+
int rc = sqlite3_prepare_v2(gravity_db, querystr, -1, read_stmt_p, NULL);
22122213
if( rc != SQLITE_OK ){
22132214
*message = sqlite3_errmsg(gravity_db);
22142215
log_err("gravityDB_readTable(%d => (%s)) - SQL error prepare (%i): %s => %s",
@@ -2220,27 +2221,29 @@ bool gravityDB_readTable(const enum gravity_list_type listtype,
22202221
}
22212222

22222223
// Bind item to prepared statement (if requested)
2223-
int idx = sqlite3_bind_parameter_index(read_stmt, ":item");
2224-
if(idx > 0 && (rc = sqlite3_bind_text(read_stmt, idx, like_name, -1, SQLITE_TRANSIENT)) != SQLITE_OK)
2224+
int idx = sqlite3_bind_parameter_index(*read_stmt_p, ":item");
2225+
if(idx > 0 && (rc = sqlite3_bind_text(*read_stmt_p, idx, like_name, -1, SQLITE_TRANSIENT)) != SQLITE_OK)
22252226
{
22262227
*message = sqlite3_errmsg(gravity_db);
22272228
log_err("gravityDB_readTable(%d => (%s), %s): Failed to bind item (error %d) - %s",
22282229
listtype, type, like_name, rc, *message);
2229-
sqlite3_finalize(read_stmt);
2230+
sqlite3_finalize(*read_stmt_p);
2231+
*read_stmt_p = NULL;
22302232
if(!exact)
22312233
free(like_name);
22322234
free(querystr);
22332235
return false;
22342236
}
22352237

22362238
// Bind ids to prepared statement (if requested)
2237-
idx = sqlite3_bind_parameter_index(read_stmt, ":ids");
2238-
if(idx > 0 && (rc = sqlite3_bind_text(read_stmt, idx, ids, -1, SQLITE_STATIC)) != SQLITE_OK)
2239+
idx = sqlite3_bind_parameter_index(*read_stmt_p, ":ids");
2240+
if(idx > 0 && (rc = sqlite3_bind_text(*read_stmt_p, idx, ids, -1, SQLITE_STATIC)) != SQLITE_OK)
22392241
{
22402242
*message = sqlite3_errmsg(gravity_db);
22412243
log_err("gravityDB_readTable(%d => (%s), %s): Failed to bind ids (error %d) - %s",
22422244
listtype, type, like_name, rc, *message);
2243-
sqlite3_finalize(read_stmt);
2245+
sqlite3_finalize(*read_stmt_p);
2246+
*read_stmt_p = NULL;
22442247
if(!exact)
22452248
free(like_name);
22462249
free(querystr);
@@ -2263,7 +2266,8 @@ bool gravityDB_readTable(const enum gravity_list_type listtype,
22632266
return true;
22642267
}
22652268

2266-
bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *row, const char **message)
2269+
bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *row, const char **message,
2270+
sqlite3_stmt *read_stmt)
22672271
{
22682272
// Perform step
22692273
const int rc = sqlite3_step(read_stmt);
@@ -2416,7 +2420,7 @@ bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *
24162420
}
24172421

24182422
// Finalize statement of a gravity database transaction
2419-
void gravityDB_readTableFinalize(void)
2423+
void gravityDB_readTableFinalize(sqlite3_stmt *read_stmt)
24202424
{
24212425
// Finalize statement
24222426
sqlite3_finalize(read_stmt);

src/database/gravity-db.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "datastructure.h"
1515
// Definition of struct regexData
1616
#include "regex_r.h"
17+
// SQLite3
18+
#include "database/sqlite3.h"
1719

1820
// Table row record, not all fields are used by all tables
1921
typedef struct {
@@ -62,9 +64,11 @@ bool gravityDB_get_regex_client_groups(clientsData *client, const unsigned int n
6264
const unsigned char type, const char* table);
6365

6466
bool gravityDB_readTable(const enum gravity_list_type listtype, const char *filter,
65-
const char **message, const bool exact, const char *ids);
66-
bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *row, const char **message);
67-
void gravityDB_readTableFinalize(void);
67+
const char **message, const bool exact, const char *ids,
68+
sqlite3_stmt **stmt);
69+
bool gravityDB_readTableGetRow(const enum gravity_list_type listtype, tablerow *row, const char **message,
70+
sqlite3_stmt *stmt);
71+
void gravityDB_readTableFinalize(sqlite3_stmt *stmt);
6872
bool gravityDB_addToTable(const enum gravity_list_type listtype, tablerow *row,
6973
const char **message, const enum http_method method);
7074
bool gravityDB_delFromTable(const enum gravity_list_type listtype, const cJSON* array, unsigned int *deleted, const char **message);

0 commit comments

Comments
 (0)