|
|
|
|
@ -35,7 +35,7 @@ using std::string;
|
|
|
|
|
using std::vector;
|
|
|
|
|
|
|
|
|
|
const int SIGNAL_NUM = 5;
|
|
|
|
|
const string base_address { "http://localhost:6070/sync/" };
|
|
|
|
|
const string base_address { "http://proxysql:6070/sync/" };
|
|
|
|
|
|
|
|
|
|
using params = std::string;
|
|
|
|
|
using signal_t = int;
|
|
|
|
|
@ -56,11 +56,22 @@ int main(int argc, char** argv) {
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diag("=== Regression Test #3838: RESTAPI Script Execution & Signals ===");
|
|
|
|
|
diag("This test verifies that scripts executed via ProxySQL RESTAPI");
|
|
|
|
|
diag("are not improperly interrupted by signals.");
|
|
|
|
|
diag("The test strategy is:");
|
|
|
|
|
diag("1. Register scripts in ProxySQL RESTAPI routes.");
|
|
|
|
|
diag("2. Issue multiple POST requests to these endpoints.");
|
|
|
|
|
diag("3. Issue various signals (SIGCONT, SIGSTOP, SIGTERM) to the child processes.");
|
|
|
|
|
diag("4. Verify that ProxySQL correctly reports exit statuses and handles timeouts.");
|
|
|
|
|
diag("==================================================================");
|
|
|
|
|
|
|
|
|
|
plan(endpoint_requests.size());
|
|
|
|
|
|
|
|
|
|
MYSQL* proxysql_admin = mysql_init(NULL);
|
|
|
|
|
|
|
|
|
|
// Initialize connections
|
|
|
|
|
diag("Connecting to ProxySQL Admin at %s:%d as %s", cl.host, cl.admin_port, cl.admin_username);
|
|
|
|
|
if (!proxysql_admin) {
|
|
|
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin));
|
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
@ -71,12 +82,14 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enable 'RESTAPI'
|
|
|
|
|
diag("Enabling RESTAPI on port 6070");
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "SET admin-restapi_enabled='true'");
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "SET admin-restapi_port=6070");
|
|
|
|
|
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "LOAD ADMIN VARIABLES TO RUNTIME");
|
|
|
|
|
|
|
|
|
|
// Clean current 'restapi_routes' if any
|
|
|
|
|
diag("Configuring RESTAPI routes...");
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "DELETE FROM restapi_routes");
|
|
|
|
|
|
|
|
|
|
// Configure restapi_routes to be used
|
|
|
|
|
@ -102,6 +115,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load RESTAPI
|
|
|
|
|
diag("Loading RESTAPI to runtime");
|
|
|
|
|
MYSQL_QUERY(proxysql_admin, "LOAD RESTAPI TO RUNTIME");
|
|
|
|
|
|
|
|
|
|
// Sensible wait until the new configured enpoints are ready. Use the first enpoint for the check
|
|
|
|
|
@ -109,6 +123,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
const string full_endpoint {
|
|
|
|
|
base_address + std::get<0>(first_request_tuple) + "/"
|
|
|
|
|
};
|
|
|
|
|
diag("Waiting for endpoint %s to be ready...", full_endpoint.c_str());
|
|
|
|
|
int endpoint_timeout = wait_post_enpoint_ready(full_endpoint, std::get<1>(first_request_tuple), 10, 500);
|
|
|
|
|
|
|
|
|
|
if (endpoint_timeout) {
|
|
|
|
|
@ -125,12 +140,15 @@ int main(int argc, char** argv) {
|
|
|
|
|
const int signal = std::get<3>(request);
|
|
|
|
|
const int exp_child_exit_st = std::get<4>(request);
|
|
|
|
|
|
|
|
|
|
diag("Processing request: endpoint=%s params=%s exp_rc=%ld signal=%d", endpoint.c_str(), params.c_str(), exp_rc, signal);
|
|
|
|
|
|
|
|
|
|
string post_out_err { "" };
|
|
|
|
|
uint64_t curl_res_code = 0;
|
|
|
|
|
|
|
|
|
|
CURLcode post_err = CURLE_HTTP_POST_ERROR;
|
|
|
|
|
|
|
|
|
|
// 1. Perform the POST operation
|
|
|
|
|
diag(" Starting POST request in separate thread...");
|
|
|
|
|
std::thread post_op_th([&] () -> void {
|
|
|
|
|
post_err = perform_simple_post(endpoint, params, curl_res_code, post_out_err);
|
|
|
|
|
});
|
|
|
|
|
@ -142,6 +160,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
int waited = 0;
|
|
|
|
|
int e_res= 0;
|
|
|
|
|
|
|
|
|
|
diag(" Waiting for child process to spawn...");
|
|
|
|
|
while (waited < timeout) {
|
|
|
|
|
e_res = exec("ps aux | grep -e \"[/]bin/sh.*.simple_sleep.sh\" | awk '{print $2}'", s_pid);
|
|
|
|
|
|
|
|
|
|
@ -165,6 +184,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
int pid = std::stol(s_pid);
|
|
|
|
|
int k_res = 0;
|
|
|
|
|
|
|
|
|
|
diag(" Sending %d signals to PID %d...", SIGNAL_NUM, pid);
|
|
|
|
|
if (signal == SIGCONT) {
|
|
|
|
|
for (int i = 0; i < SIGNAL_NUM; i++) {
|
|
|
|
|
k_res = kill(pid, SIGSTOP);
|
|
|
|
|
@ -186,7 +206,9 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diag(" Waiting for POST request to complete...");
|
|
|
|
|
post_op_th.join();
|
|
|
|
|
diag(" Request completed with curl_res_code=%ld and post_err=%d", curl_res_code, post_err);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
int child_exit_st = 0;
|
|
|
|
|
@ -197,6 +219,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
if (j_curl_err.contains("error_code")) {
|
|
|
|
|
child_exit_st = std::stol(j_curl_err["error_code"].get<string>());
|
|
|
|
|
}
|
|
|
|
|
diag(" Parsed response: child_exit_st=%d", child_exit_st);
|
|
|
|
|
|
|
|
|
|
// NOTE: This is pointless because the value doesn't change, but it's a demonstration on how to
|
|
|
|
|
// recover child process exit statuses for debugging purposes.
|
|
|
|
|
|