Skip to content

Instantly share code, notes, and snippets.

@hirose31
Created February 6, 2019 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hirose31/78ff80085119ec0fb485d35c4cb360a1 to your computer and use it in GitHub Desktop.
Save hirose31/78ff80085119ec0fb485d35c4cb360a1 to your computer and use it in GitHub Desktop.
/* -*- mode: c; coding: utf-8 -*-
https://bugs.mysql.com/bug.php?id=92394
How to reproduce
gcc simple-query.c $(mysql_config --cflags) $(mysql_config --libs) -o simple-query
MYSQL_USER=scott MYSQL_PWD=tiger ./simple-query
mysql client version: 50724
> while true; do kill -USR1 5922 || break; sleep 15; done
> do_query
< 1
> safe_sleep: 110
caught signal: 10
caught signal: 10
caught signal: 10
caught signal: 10
caught signal: 10
caught signal: 10
caught signal: 10
caught signal: 10
> do_query
caught signal: 10
^C
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <mysql.h>
void signal_handler(int signum) {
fprintf(stderr, "caught signal: %d\n", signum);
}
void do_query(MYSQL mysql) {
int r;
MYSQL_RES *result;
MYSQL_ROW row;
fprintf(stderr, "> do_query\n");
char *stmt = "select 1";
unsigned int stmt_len = strlen(stmt);
r = mysql_real_query(&mysql, stmt, stmt_len);
if (r != 0) {
fprintf(stderr, "query: %s\n", mysql_error(&mysql));
exit(1);
}
result = mysql_store_result(&mysql);
while ((row = mysql_fetch_row(result))) {
printf("< %s\n", row[0]);
}
mysql_free_result(result);
}
void safe_sleep(time_t sec) {
int r;
struct timespec req, rem;
fprintf(stderr, "> safe_sleep: %ld\n", sec);
req.tv_sec = sec;
req.tv_nsec = 0;
for (;;) {
r = nanosleep(&req, &rem);
if (r == 0) {
break;
} else {
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
}
}
}
int main(int argc, char** argv) {
int r;
char *host = getenv("MYSQL_HOST");
char *user = getenv("MYSQL_USER");
char *password = getenv("MYSQL_PWD");
MYSQL mysql;
struct sigaction sa;
if (host == NULL)
host = "127.0.0.1";
if (user == NULL)
user = "root";
if (fork() == 0) {
pid_t p_pid = getppid();
char cmd[255];
// char *signal = "TERM";
// char *signal = "ALRM";
char *signal = "USR1";
sprintf(cmd, "while true; do kill -%s %d || break; sleep 15; done",
signal,
p_pid);
fprintf(stderr, "> %s\n", cmd);
sleep(3);
execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
perror("failed to exec");
exit(1);
}
memset(&sa, 0, sizeof(sa));
sa.sa_handler = signal_handler;
if (sigaction(SIGTERM, &sa, NULL) != 0) {
perror("sigaction");
exit(1);
}
if (sigaction(SIGALRM, &sa, NULL) != 0) {
perror("sigaction");
exit(1);
}
if (sigaction(SIGUSR1, &sa, NULL) != 0) {
perror("sigaction");
exit(1);
}
fprintf(stderr, "mysql client version: %ld\n", mysql_get_client_version());
mysql_init(&mysql);
if (!mysql_real_connect(&mysql, host, user, password, "", 3306, NULL, 0)) {
fprintf(stderr, "connect: %s\n", mysql_error(&mysql));
exit(1);
}
int sleep_second = 110;
for (;;) {
do_query(mysql);
safe_sleep(sleep_second);
sleep_second += 10;
}
mysql_close(&mysql);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment