Skip to content

Commit 91e2275

Browse files
background thread v1
v3
1 parent 220a7a8 commit 91e2275

31 files changed

Lines changed: 1844 additions & 25 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
SET PERSIST vsql_allow_preview_extensions = ON;
2+
INSTALL EXTENSION vsql_lifecycle_test;
3+
# Thread should NOT be running yet (enabled defaults to OFF)
4+
SELECT COUNT(*) FROM performance_schema.processlist
5+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
6+
COUNT(*)
7+
0
8+
SET GLOBAL vsql_lifecycle_test.monitor_enabled = ON;
9+
# Thread should appear in processlist after enable
10+
SELECT id, user, info FROM performance_schema.processlist
11+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
12+
ORDER BY id;
13+
id user info
14+
<id> vef_worker vsql_lifecycle_test/monitor
15+
# Tick count should be positive (thread ticks every 100ms)
16+
SELECT vsql_lifecycle_test.tick_count() > 0;
17+
vsql_lifecycle_test.tick_count() > 0
18+
1
19+
SET GLOBAL vsql_lifecycle_test.monitor_enabled = OFF;
20+
# Thread is gone from processlist after disable
21+
SELECT COUNT(*) FROM performance_schema.processlist
22+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
23+
COUNT(*)
24+
0
25+
UNINSTALL EXTENSION vsql_lifecycle_test;
26+
SET PERSIST vsql_allow_preview_extensions = OFF;
27+
RESET PERSIST vsql_allow_preview_extensions;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
SET PERSIST vsql_allow_preview_extensions = ON;
2+
INSTALL EXTENSION vsql_lifecycle_test;
3+
SET PERSIST vsql_lifecycle_test.monitor_enabled = ON;
4+
# Tick count should be positive: thread is running
5+
SELECT vsql_lifecycle_test.tick_count() > 0;
6+
vsql_lifecycle_test.tick_count() > 0
7+
1
8+
# Restart server (extension reinstated from villagesql.extensions)
9+
# restart: --veb-dir=MYSQLTEST_VARDIR/mysqld.1/veb/
10+
# Monitor thread visible in processlist after restart (enabled was persisted)
11+
SELECT id, user, info FROM performance_schema.processlist
12+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
13+
ORDER BY id;
14+
id user info
15+
<id> vef_worker vsql_lifecycle_test/monitor
16+
# Tick count >= 0 confirms thread restarted
17+
SELECT vsql_lifecycle_test.tick_count() >= 0;
18+
vsql_lifecycle_test.tick_count() >= 0
19+
1
20+
SET PERSIST vsql_lifecycle_test.monitor_enabled = OFF;
21+
UNINSTALL EXTENSION vsql_lifecycle_test;
22+
SET PERSIST vsql_allow_preview_extensions = OFF;
23+
# Thread is gone from processlist after uninstall
24+
SELECT COUNT(*) FROM performance_schema.processlist
25+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
26+
COUNT(*)
27+
0
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
SET PERSIST vsql_allow_preview_extensions = ON;
2+
INSTALL EXTENSION vsql_thread_worker_test;
3+
# Thread should NOT be running yet
4+
SELECT vsql_thread_worker_test.active_port();
5+
vsql_thread_worker_test.active_port()
6+
0
7+
SET GLOBAL vsql_thread_worker_test.listener_enabled = ON;
8+
# Connect and send PING
9+
SELECT vsql_thread_worker_test.active_port() INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/tw_port.txt';
10+
# last_command should be PING
11+
SELECT vsql_thread_worker_test.last_command();
12+
vsql_thread_worker_test.last_command()
13+
PING
14+
# Connect and send HELLO
15+
SELECT vsql_thread_worker_test.active_port() INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/tw_port.txt';
16+
# last_command should now be HELLO
17+
SELECT vsql_thread_worker_test.last_command();
18+
vsql_thread_worker_test.last_command()
19+
HELLO
20+
SET GLOBAL vsql_thread_worker_test.listener_enabled = OFF;
21+
# After disable: active_port should be 0
22+
SELECT vsql_thread_worker_test.active_port();
23+
vsql_thread_worker_test.active_port()
24+
0
25+
UNINSTALL EXTENSION vsql_thread_worker_test;
26+
SET PERSIST vsql_allow_preview_extensions = OFF;
27+
RESET PERSIST vsql_allow_preview_extensions;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Test thread_worker lifecycle: enable/disable via sys var.
2+
#
3+
# Verifies:
4+
# - INSTALL EXTENSION registers the extension; thread does NOT start yet
5+
# - Setting monitor_enabled = ON starts the background thread
6+
# - The thread appears in performance_schema.processlist while enabled
7+
# - tick_count() advances (thread is actually looping)
8+
# - Setting monitor_enabled = OFF stops the thread
9+
# - UNINSTALL EXTENSION cleans up cleanly
10+
11+
# The processlist checks require PSI thread instrumentation.
12+
if (`SELECT COUNT(*)=0 FROM performance_schema.threads`)
13+
{
14+
skip Needs PSI thread instrumentation (DISABLE_PSI_THREAD must be 0);
15+
}
16+
17+
SET PERSIST vsql_allow_preview_extensions = ON;
18+
19+
INSTALL EXTENSION vsql_lifecycle_test;
20+
21+
--echo # Thread should NOT be running yet (enabled defaults to OFF)
22+
SELECT COUNT(*) FROM performance_schema.processlist
23+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
24+
25+
SET GLOBAL vsql_lifecycle_test.monitor_enabled = ON;
26+
27+
--let $wait_condition = SELECT COUNT(*) > 0 FROM performance_schema.processlist WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
28+
--source include/wait_condition.inc
29+
30+
--echo # Thread should appear in processlist after enable
31+
--replace_column 1 <id>
32+
SELECT id, user, info FROM performance_schema.processlist
33+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
34+
ORDER BY id;
35+
36+
--let $wait_condition = SELECT vsql_lifecycle_test.tick_count() > 0
37+
--source include/wait_condition.inc
38+
39+
--echo # Tick count should be positive (thread ticks every 100ms)
40+
SELECT vsql_lifecycle_test.tick_count() > 0;
41+
42+
SET GLOBAL vsql_lifecycle_test.monitor_enabled = OFF;
43+
44+
--echo # Thread is gone from processlist after disable
45+
SELECT COUNT(*) FROM performance_schema.processlist
46+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
47+
48+
UNINSTALL EXTENSION vsql_lifecycle_test;
49+
50+
SET PERSIST vsql_allow_preview_extensions = OFF;
51+
RESET PERSIST vsql_allow_preview_extensions;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Test that a thread_worker restarts after server restart when enabled = ON
2+
# was persisted.
3+
#
4+
# The tick_count() VDF increments every 100ms from the background monitor
5+
# thread. After a server restart the extension reloads and the enabled
6+
# sys var is restored from mysqld-auto.cnf, restarting the thread.
7+
8+
# The processlist checks require PSI thread instrumentation.
9+
if (`SELECT COUNT(*)=0 FROM performance_schema.threads`)
10+
{
11+
skip Needs PSI thread instrumentation (DISABLE_PSI_THREAD must be 0);
12+
}
13+
14+
SET PERSIST vsql_allow_preview_extensions = ON;
15+
INSTALL EXTENSION vsql_lifecycle_test;
16+
SET PERSIST vsql_lifecycle_test.monitor_enabled = ON;
17+
18+
--let $wait_condition = SELECT vsql_lifecycle_test.tick_count() > 0
19+
--source include/wait_condition.inc
20+
21+
--echo # Tick count should be positive: thread is running
22+
SELECT vsql_lifecycle_test.tick_count() > 0;
23+
24+
--echo # Restart server (extension reinstated from villagesql.extensions)
25+
--let $veb_dir = `SELECT @@veb_dir`
26+
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
27+
--let $restart_parameters = restart: --veb-dir=$veb_dir
28+
--source include/restart_mysqld.inc
29+
30+
--let $wait_condition = SELECT COUNT(*) > 0 FROM performance_schema.processlist WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
31+
--source include/wait_condition.inc
32+
33+
--echo # Monitor thread visible in processlist after restart (enabled was persisted)
34+
--replace_column 1 <id>
35+
SELECT id, user, info FROM performance_schema.processlist
36+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor'
37+
ORDER BY id;
38+
39+
--echo # Tick count >= 0 confirms thread restarted
40+
SELECT vsql_lifecycle_test.tick_count() >= 0;
41+
42+
SET PERSIST vsql_lifecycle_test.monitor_enabled = OFF;
43+
UNINSTALL EXTENSION vsql_lifecycle_test;
44+
SET PERSIST vsql_allow_preview_extensions = OFF;
45+
46+
--echo # Thread is gone from processlist after uninstall
47+
SELECT COUNT(*) FROM performance_schema.processlist
48+
WHERE user = 'vef_worker' AND info = 'vsql_lifecycle_test/monitor';
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Test thread_worker dynamic wakeup control.
2+
#
3+
# Verifies:
4+
# - ENABLE opens socket on OS-assigned port; active_port() returns it
5+
# - POLL_FD fires on connection; worker reads command, stores last_command
6+
# - last_command() VDF returns the received string
7+
# - DISABLE closes socket; active_port() returns 0
8+
9+
SET PERSIST vsql_allow_preview_extensions = ON;
10+
11+
INSTALL EXTENSION vsql_thread_worker_test;
12+
13+
--echo # Thread should NOT be running yet
14+
SELECT vsql_thread_worker_test.active_port();
15+
16+
SET GLOBAL vsql_thread_worker_test.listener_enabled = ON;
17+
18+
--echo # Connect and send PING
19+
--let $port_file = $MYSQLTEST_VARDIR/tmp/tw_port.txt
20+
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
21+
eval SELECT vsql_thread_worker_test.active_port() INTO OUTFILE '$port_file';
22+
--perl
23+
use IO::Socket::INET;
24+
open(my $fh, '<', $ENV{MYSQLTEST_VARDIR} . '/tmp/tw_port.txt') or die $!;
25+
my $port = <$fh>; chomp $port;
26+
close($fh);
27+
my $sock = IO::Socket::INET->new(
28+
PeerAddr => "127.0.0.1",
29+
PeerPort => $port,
30+
Proto => "tcp",
31+
Timeout => 5,
32+
) or die "connect failed: $!";
33+
$sock->autoflush(1);
34+
print $sock "PING\n";
35+
shutdown($sock, 1);
36+
close($sock);
37+
EOF
38+
--remove_file $port_file
39+
40+
--let $wait_condition = SELECT vsql_thread_worker_test.last_command() = 'PING'
41+
--source include/wait_condition.inc
42+
43+
--echo # last_command should be PING
44+
SELECT vsql_thread_worker_test.last_command();
45+
46+
--echo # Connect and send HELLO
47+
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
48+
eval SELECT vsql_thread_worker_test.active_port() INTO OUTFILE '$port_file';
49+
--perl
50+
use IO::Socket::INET;
51+
open(my $fh, '<', $ENV{MYSQLTEST_VARDIR} . '/tmp/tw_port.txt') or die $!;
52+
my $port = <$fh>; chomp $port;
53+
close($fh);
54+
my $sock = IO::Socket::INET->new(
55+
PeerAddr => "127.0.0.1",
56+
PeerPort => $port,
57+
Proto => "tcp",
58+
Timeout => 5,
59+
) or die "connect failed: $!";
60+
$sock->autoflush(1);
61+
print $sock "HELLO\n";
62+
shutdown($sock, 1);
63+
close($sock);
64+
EOF
65+
--remove_file $port_file
66+
67+
--let $wait_condition = SELECT vsql_thread_worker_test.last_command() = 'HELLO'
68+
--source include/wait_condition.inc
69+
70+
--echo # last_command should now be HELLO
71+
SELECT vsql_thread_worker_test.last_command();
72+
73+
SET GLOBAL vsql_thread_worker_test.listener_enabled = OFF;
74+
75+
--echo # After disable: active_port should be 0
76+
SELECT vsql_thread_worker_test.active_port();
77+
78+
UNINSTALL EXTENSION vsql_thread_worker_test;
79+
80+
SET PERSIST vsql_allow_preview_extensions = OFF;
81+
RESET PERSIST vsql_allow_preview_extensions;

sql/mysqld.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,12 @@ static void close_connections(void) {
24392439
scheduler object(static member in Events class)
24402440
*/
24412441
Events::deinit();
2442+
2443+
// Unload VEF extensions. All client connections are now closed so no VDF
2444+
// calls are in flight. on_unload callbacks stop background threads and remove
2445+
// their THDs from Global_THD_manager so wait_till_no_thd() can complete.
2446+
villagesql::deinit_extension_infrastructure();
2447+
24422448
DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)",
24432449
thd_manager->get_thd_count()));
24442450
/*
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright (c) 2026 VillageSQL Contributors
2+
#
3+
# This program is free software; you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License, version 2.0,
5+
# as published by the Free Software Foundation.
6+
#
7+
# This program is designed to work with certain software (including
8+
# but not limited to OpenSSL) that is licensed under separate terms,
9+
# as designated in a particular file or component or in included license
10+
# documentation. The authors of MySQL hereby grant you an additional
11+
# permission to link the program and your derivative works with the
12+
# separately licensed software that they have either included with
13+
# the program or referenced in the documentation.
14+
#
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License, version 2.0, for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program; if not, write to the Free Software
22+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23+
24+
# Quick start (standalone):
25+
# mkdir build && cd build
26+
# cmake .. -DCMAKE_PREFIX_PATH=/path/to/villagesql-extension-sdk
27+
# make
28+
# make install DESTDIR=/path/to/villagesql/lib/veb
29+
30+
cmake_minimum_required(VERSION 3.16)
31+
project(vsql_http_monitor_extension)
32+
33+
set(CMAKE_CXX_STANDARD 17)
34+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
35+
36+
set(EXTENSION_NAME "vsql_http_monitor")
37+
38+
find_package(VillageSQLExtensionFramework REQUIRED)
39+
40+
include_directories(${VillageSQLExtensionFramework_INCLUDE_DIR})
41+
42+
add_library(extension SHARED
43+
src/extension.cc
44+
)
45+
46+
target_compile_options(extension PRIVATE -fPIC)
47+
48+
VEF_CREATE_VEB(
49+
NAME ${EXTENSION_NAME}
50+
LIBRARY_TARGET extension
51+
MANIFEST ${CMAKE_CURRENT_SOURCE_DIR}/manifest.json
52+
)
53+
54+
install(FILES ${VEB_OUTPUT} DESTINATION ".")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "vsql_http_monitor",
3+
"version": "0.0.1",
4+
"description": "Minimal HTTP monitoring endpoint example using on_load/on_unload and poll_fd",
5+
"author": "VillageSQL Community",
6+
"license": "GPL-2.0"
7+
}

0 commit comments

Comments
 (0)