Skip to content

Commit cb26e15

Browse files
committed
fix: worker_restart without security definer
1 parent 8e34a8e commit cb26e15

6 files changed

+57
-8
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# PG_NET
22
*A PostgreSQL extension that enables asynchronous (non-blocking) HTTP/HTTPS requests with SQL*.
33

4-
Requires libcurl >= 7.83.
4+
Requires libcurl >= 7.83. Compatible with PostgreSQL > = 12.
55

66
![PostgreSQL version](https://img.shields.io/badge/postgresql-12+-blue.svg)
77
[![License](https://img.shields.io/pypi/l/markdown-subtemplate.svg)](https://github.com/supabase/pg_net/blob/master/LICENSE)

sql/pg_net--0.11.0--0.11.1.sql

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ alter function net._http_collect_response ( bigint, boolean) security invoker;
88

99
alter function net.http_collect_response ( bigint, boolean) security invoker;
1010

11+
create or replace function net.worker_restart()
12+
returns bool
13+
language 'c'
14+
as 'pg_net';
15+
1116
grant usage on schema net to PUBLIC;
1217
grant all on all sequences in schema net to PUBLIC;
1318
grant all on all tables in schema net to PUBLIC;

sql/pg_net.sql

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ create or replace function net._encode_url_with_params_array(url text, params_ar
9696
immutable
9797
as 'pg_net';
9898

99+
create or replace function net.worker_restart()
100+
returns bool
101+
language 'c'
102+
as 'pg_net';
99103

100104
-- Interface to make an async request
101105
-- API: Public

src/worker.c

+34-7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include <string.h>
3131
#include <inttypes.h>
3232

33+
#include <storage/shmem.h>
34+
3335
#include "util.h"
3436
#include "core.h"
3537

@@ -40,17 +42,25 @@ _Static_assert(LIBCURL_VERSION_NUM >= MIN_LIBCURL_VERSION_NUM, REQUIRED_LIBCURL_
4042

4143
PG_MODULE_MAGIC;
4244

43-
static char *guc_ttl;
44-
static int guc_batch_size;
45-
static char* guc_database_name;
46-
static MemoryContext CurlMemContext = NULL;
45+
static char* guc_ttl;
46+
static int guc_batch_size;
47+
static char* guc_database_name;
48+
static MemoryContext CurlMemContext = NULL;
49+
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
50+
static long latch_timeout = 1000;
51+
static volatile sig_atomic_t got_sigterm = false;
52+
static volatile sig_atomic_t got_sighup = false;
53+
static bool* restart_worker = NULL;
4754

4855
void _PG_init(void);
4956
PGDLLEXPORT void pg_net_worker(Datum main_arg) pg_attribute_noreturn();
5057

51-
static long latch_timeout = 1000;
52-
static volatile sig_atomic_t got_sigterm = false;
53-
static volatile sig_atomic_t got_sighup = false;
58+
PG_FUNCTION_INFO_V1(worker_restart);
59+
Datum worker_restart(PG_FUNCTION_ARGS) {
60+
bool result = DatumGetBool(DirectFunctionCall1(pg_reload_conf, (Datum) NULL)); // reload the config
61+
*restart_worker = true;
62+
PG_RETURN_BOOL(result && *restart_worker); // TODO is not necessary to return a bool here, but we do it to maintain backward compatibility
63+
}
5464

5565
static void
5666
handle_sigterm(SIGNAL_ARGS)
@@ -141,6 +151,12 @@ void pg_net_worker(Datum main_arg) {
141151
ProcessConfigFile(PGC_SIGHUP);
142152
}
143153

154+
if (restart_worker && *restart_worker) {
155+
*restart_worker = false;
156+
elog(INFO, "Restarting pg_net worker");
157+
break;
158+
}
159+
144160
delete_expired_responses(guc_ttl, guc_batch_size);
145161

146162
consume_request_queue(lstate.curl_mhandle, guc_batch_size, CurlMemContext);
@@ -206,6 +222,14 @@ void pg_net_worker(Datum main_arg) {
206222
proc_exit(EXIT_FAILURE);
207223
}
208224

225+
static void net_shmem_startup(void) {
226+
if (prev_shmem_startup_hook)
227+
prev_shmem_startup_hook();
228+
229+
restart_worker = ShmemAlloc(sizeof(bool));
230+
*restart_worker = false;
231+
}
232+
209233
void _PG_init(void) {
210234
if (IsBinaryUpgrade) {
211235
return;
@@ -226,6 +250,9 @@ void _PG_init(void) {
226250
.bgw_restart_time = 1,
227251
});
228252

253+
prev_shmem_startup_hook = shmem_startup_hook;
254+
shmem_startup_hook = net_shmem_startup;
255+
229256
CurlMemContext = AllocSetContextCreate(TopMemoryContext,
230257
"pg_net curl context",
231258
ALLOCSET_DEFAULT_MINSIZE,

test/test_privileges.py

+11
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ def test_net_on_another_role(sess):
6363
).fetchone()
6464
assert response[0] == "SUCCESS"
6565

66+
## can use the net.worker_restart function
67+
response = sess.execute(
68+
text(
69+
"""
70+
set local role to another;
71+
select net.worker_restart();
72+
"""
73+
)
74+
).fetchone()
75+
assert response[0] == True
76+
6677
sess.execute(text("""
6778
set local role postgres;
6879
drop role another;

test/test_worker_error.py

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
def test_success_when_worker_is_up(sess):
66
"""net.check_worker_is_up should not return anything when the worker is running"""
77

8+
time.sleep(1) # wait if another test did a net.worker_restart()
9+
810
(result,) = sess.execute(text("""
911
select net.check_worker_is_up();
1012
""")).fetchone()

0 commit comments

Comments
 (0)