summaryrefslogtreecommitdiffstats
path: root/mysys/thr_alarm.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-01 18:15:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-07-01 18:15:00 +0000
commita2a2e32c02643a0cec111511220227703fda1cd5 (patch)
tree69cc2b631234c2a8e026b9cd4d72676c61c594df /mysys/thr_alarm.c
parentReleasing progress-linux version 1:10.11.8-1~progress7.99u1. (diff)
downloadmariadb-a2a2e32c02643a0cec111511220227703fda1cd5.tar.xz
mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.zip
Merging upstream version 1:11.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mysys/thr_alarm.c')
-rw-r--r--mysys/thr_alarm.c844
1 files changed, 0 insertions, 844 deletions
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
deleted file mode 100644
index 4e2db203..00000000
--- a/mysys/thr_alarm.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates
- Copyright (c) 2012, 2014, SkySQL Ab
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
-
-/* To avoid problems with alarms in debug code, we disable DBUG here */
-#define FORCE_DBUG_OFF
-#include "mysys_priv.h"
-#include <my_global.h>
-
-#if !defined(DONT_USE_THR_ALARM)
-#include <errno.h>
-#include <my_pthread.h>
-#include <signal.h>
-#include <my_sys.h>
-#include <m_string.h>
-#include <queues.h>
-#include "thr_alarm.h"
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h> /* AIX needs this for fd_set */
-#endif
-
-#ifndef ETIME
-#define ETIME ETIMEDOUT
-#endif
-
-#ifdef DBUG_OFF
-#define reset_index_in_queue(alarm_data)
-#else
-#define reset_index_in_queue(alarm_data) alarm_data->index_in_queue= 0;
-#endif /* DBUG_OFF */
-
-#ifndef USE_ONE_SIGNAL_HAND
-#define one_signal_hand_sigmask(A,B,C) pthread_sigmask((A), (B), (C))
-#else
-#define one_signal_hand_sigmask(A,B,C)
-#endif
-
-my_bool thr_alarm_inited= 0, my_disable_thr_alarm= 0;
-
-#if !defined(_WIN32)
-
-uint thr_client_alarm;
-static int alarm_aborted=1; /* No alarm thread */
-volatile my_bool alarm_thread_running= 0;
-time_t next_alarm_expire_time= ~ (time_t) 0;
-static sig_handler process_alarm_part2(int sig);
-
-static mysql_mutex_t LOCK_alarm;
-static mysql_cond_t COND_alarm;
-static sigset_t full_signal_set;
-static QUEUE alarm_queue;
-static uint max_used_alarms=0;
-pthread_t alarm_thread;
-
-#define MY_THR_ALARM_QUEUE_EXTENT 10
-
-#ifdef USE_ALARM_THREAD
-static void *alarm_handler(void *arg);
-#define reschedule_alarms() mysql_cond_signal(&COND_alarm)
-#else
-#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM)
-#endif
-
-static sig_handler thread_alarm(int sig __attribute__((unused)));
-
-static int compare_ulong(void *not_used __attribute__((unused)),
- uchar *a_ptr,uchar* b_ptr)
-{
- ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr);
- return (a < b) ? -1 : (a == b) ? 0 : 1;
-}
-
-void init_thr_alarm(uint max_alarms)
-{
- sigset_t s;
- DBUG_ENTER("init_thr_alarm");
- alarm_aborted=0;
- next_alarm_expire_time= ~ (time_t) 0;
- init_queue(&alarm_queue, max_alarms+1, offsetof(ALARM,expire_time), 0,
- compare_ulong, NullS, offsetof(ALARM, index_in_queue)+1,
- MY_THR_ALARM_QUEUE_EXTENT);
- sigfillset(&full_signal_set); /* Neaded to block signals */
- mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST);
- mysql_cond_init(key_COND_alarm, &COND_alarm, NULL);
- thr_client_alarm= SIGUSR1;
- my_sigset(thr_client_alarm, thread_alarm);
- sigemptyset(&s);
- sigaddset(&s, THR_SERVER_ALARM);
- alarm_thread=pthread_self();
-#if defined(USE_ALARM_THREAD)
- {
- pthread_attr_t thr_attr;
- pthread_attr_init(&thr_attr);
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
- pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
- mysql_thread_create(key_thread_alarm,
- &alarm_thread, &thr_attr, alarm_handler, NULL);
- pthread_attr_destroy(&thr_attr);
- }
-#elif defined(USE_ONE_SIGNAL_HAND)
- pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */
-#else
- my_sigset(THR_SERVER_ALARM, process_alarm);
- pthread_sigmask(SIG_UNBLOCK, &s, NULL);
-#endif
- DBUG_VOID_RETURN;
-}
-
-
-void resize_thr_alarm(uint max_alarms)
-{
- mysql_mutex_lock(&LOCK_alarm);
- /*
- It's ok not to shrink the queue as there may be more pending alarms than
- than max_alarms
- */
- if (alarm_queue.elements < max_alarms)
- {
- resize_queue(&alarm_queue,max_alarms+1);
- max_used_alarms= alarm_queue.elements;
- }
- mysql_mutex_unlock(&LOCK_alarm);
-}
-
-
-/*
- Request alarm after sec seconds.
-
- SYNOPSIS
- thr_alarm()
- alrm Pointer to alarm detection
- alarm_data Structure to store in alarm queue
-
- NOTES
- This function can't be called from the alarm-handling thread.
-
- RETURN VALUES
- 0 ok
- 1 If no more alarms are allowed (aborted by process)
-
- Stores in first argument a pointer to a non-zero int which is set to 0
- when the alarm has been given
-*/
-
-my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
-{
- time_t now, next;
-#ifndef USE_ONE_SIGNAL_HAND
- sigset_t old_mask;
-#endif
- my_bool reschedule;
- struct st_my_thread_var *current_my_thread_var= my_thread_var;
- DBUG_ENTER("thr_alarm");
- DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec));
-
- if (my_disable_thr_alarm)
- {
- (*alrm)= &alarm_data->alarmed;
- alarm_data->alarmed= 1; /* Abort if interrupted */
- DBUG_RETURN(0);
- }
-
- if (unlikely(alarm_aborted))
- { /* No signal thread */
- DBUG_PRINT("info", ("alarm aborted"));
- if (alarm_aborted > 0)
- goto abort_no_unlock;
- sec= 1; /* Abort mode */
- }
-
- now= my_time(0);
- if (!alarm_data)
- {
- if (!(alarm_data=(ALARM*) my_malloc(PSI_INSTRUMENT_ME, sizeof(ALARM),
- MYF(MY_WME))))
- goto abort_no_unlock;
- alarm_data->malloced= 1;
- }
- else
- alarm_data->malloced= 0;
- next= now + sec;
- alarm_data->expire_time= next;
- alarm_data->alarmed= 0;
- alarm_data->thread= current_my_thread_var->pthread_self;
- alarm_data->thread_id= current_my_thread_var->id;
-
- one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
- mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
- if (alarm_queue.elements >= max_used_alarms)
- {
- max_used_alarms=alarm_queue.elements+1;
- }
- reschedule= (ulong) next_alarm_expire_time > (ulong) next;
- queue_insert_safe(&alarm_queue, (uchar*) alarm_data);
- assert(alarm_data->index_in_queue > 0);
-
- /* Reschedule alarm if the current one has more than sec left */
- if (unlikely(reschedule))
- {
- DBUG_PRINT("info", ("reschedule"));
- if (pthread_equal(pthread_self(),alarm_thread))
- {
- alarm(sec); /* purecov: inspected */
- next_alarm_expire_time= next;
- }
- else
- reschedule_alarms(); /* Reschedule alarms */
- }
- mysql_mutex_unlock(&LOCK_alarm);
- one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
- (*alrm)= &alarm_data->alarmed;
- DBUG_RETURN(0);
-
-abort_no_unlock:
- *alrm= 0; /* No alarm */
- DBUG_RETURN(1);
-}
-
-
-/*
- Remove alarm from list of alarms
-*/
-
-void thr_end_alarm(thr_alarm_t *alarmed)
-{
- ALARM *alarm_data;
-#ifndef USE_ONE_SIGNAL_HAND
- sigset_t old_mask;
-#endif
- DBUG_ENTER("thr_end_alarm");
-
- if (my_disable_thr_alarm)
- DBUG_VOID_RETURN;
- one_signal_hand_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
- alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed));
- mysql_mutex_lock(&LOCK_alarm);
- DBUG_ASSERT(alarm_data->index_in_queue != 0);
- DBUG_ASSERT((ALARM*) queue_element(&alarm_queue,
- alarm_data->index_in_queue) ==
- alarm_data);
- queue_remove(&alarm_queue, alarm_data->index_in_queue);
- mysql_mutex_unlock(&LOCK_alarm);
- one_signal_hand_sigmask(SIG_SETMASK,&old_mask,NULL);
- reset_index_in_queue(alarm_data);
- DBUG_VOID_RETURN;
-}
-
-/*
- Come here when some alarm in queue is due.
- Mark all alarms with are finnished in list.
- Schedule alarms to be sent again after 1-10 sec (many alarms at once)
- If alarm_aborted is set then all alarms are given and resent
- every second.
-*/
-
-sig_handler process_alarm(int sig __attribute__((unused)))
-{
- sigset_t old_mask;
-/*
- This must be first as we can't call DBUG inside an alarm for a normal thread
-*/
-
- /*
- We have to do do the handling of the alarm in a sub function,
- because otherwise we would get problems with two threads calling
- DBUG_... functions at the same time (as two threads may call
- process_alarm() at the same time
- */
-
-#ifndef USE_ALARM_THREAD
- pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask);
- mysql_mutex_lock(&LOCK_alarm);
-#endif
- process_alarm_part2(sig);
-#ifndef USE_ALARM_THREAD
-#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND)
- my_sigset(THR_SERVER_ALARM,process_alarm);
-#endif
- mysql_mutex_unlock(&LOCK_alarm);
- pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
-#endif
- return;
-}
-
-
-static sig_handler process_alarm_part2(int sig __attribute__((unused)))
-{
- ALARM *alarm_data;
- DBUG_ENTER("process_alarm");
- DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements));
-
-#if defined(MAIN) && !defined(__bsdi__)
- printf("process_alarm\n"); fflush(stdout);
-#endif
- if (likely(alarm_queue.elements))
- {
- if (unlikely(alarm_aborted))
- {
- uint i;
- for (i= queue_first_element(&alarm_queue) ;
- i <= queue_last_element(&alarm_queue) ;)
- {
- alarm_data=(ALARM*) queue_element(&alarm_queue,i);
- alarm_data->alarmed=1; /* Info to thread */
- if (pthread_equal(alarm_data->thread,alarm_thread) ||
- pthread_kill(alarm_data->thread, thr_client_alarm))
- {
-#ifdef MAIN
- printf("Warning: pthread_kill couldn't find thread!!!\n");
-#endif
- queue_remove(&alarm_queue,i); /* No thread. Remove alarm */
- reset_index_in_queue(alarm_data);
- }
- else
- i++; /* Signal next thread */
- }
-#ifndef USE_ALARM_THREAD
- if (alarm_queue.elements)
- alarm(1); /* Signal soon again */
-#endif
- }
- else
- {
- time_t now= my_time(0);
- time_t next= now+10-(now%10);
- while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now)
- {
- alarm_data->alarmed=1; /* Info to thread */
- DBUG_PRINT("info",("sending signal to waiting thread"));
- if (pthread_equal(alarm_data->thread,alarm_thread) ||
- pthread_kill(alarm_data->thread, thr_client_alarm))
- {
-#ifdef MAIN
- printf("Warning: pthread_kill couldn't find thread!!!\n");
-#endif /* MAIN */
- queue_remove_top(&alarm_queue); /* No thread. Remove alarm */
- reset_index_in_queue(alarm_data);
- if (!alarm_queue.elements)
- break;
- }
- else
- {
- alarm_data->expire_time=next;
- queue_replace_top(&alarm_queue);
- }
- }
-#ifndef USE_ALARM_THREAD
- if (alarm_queue.elements)
- {
-#ifdef __bsdi__
- alarm(0); /* Remove old alarm */
-#endif
- alarm((uint) (alarm_data->expire_time-now));
- next_alarm_expire_time= alarm_data->expire_time;
- }
-#endif
- }
- }
- else
- {
- /*
- Ensure that next time we call thr_alarm(), we will schedule a new alarm
- */
- next_alarm_expire_time= ~(time_t) 0;
- }
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Schedule all alarms now and optionally free all structures
-
- SYNPOSIS
- end_thr_alarm()
- free_structures Set to 1 if we should free memory used for
- the alarm queue.
- When we call this we should KNOW that there
- is no active alarms
- IMPLEMENTATION
- Set alarm_abort to -1 which will change the behavior of alarms as follows:
- - All old alarms will be rescheduled at once
- - All new alarms will be rescheduled to one second
-*/
-
-void end_thr_alarm(my_bool free_structures)
-{
- DBUG_ENTER("end_thr_alarm");
- if (alarm_aborted != 1) /* If memory not freed */
- {
- mysql_mutex_lock(&LOCK_alarm);
- DBUG_PRINT("info",("Rescheduling %d waiting alarms",alarm_queue.elements));
- alarm_aborted= -1; /* mark aborted */
- if (alarm_queue.elements || (alarm_thread_running && free_structures))
- {
- if (pthread_equal(pthread_self(),alarm_thread))
- alarm(1); /* Shut down everything soon */
- else
- reschedule_alarms();
- }
- if (free_structures)
- {
- struct timespec abstime;
-
- DBUG_ASSERT(!alarm_queue.elements);
-
- /* Wait until alarm thread dies */
- set_timespec(abstime, 10); /* Wait up to 10 seconds */
- while (alarm_thread_running)
- {
- int error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
- if (error == ETIME || error == ETIMEDOUT)
- break; /* Don't wait forever */
- }
- delete_queue(&alarm_queue);
- alarm_aborted= 1;
- mysql_mutex_unlock(&LOCK_alarm);
- if (!alarm_thread_running) /* Safety */
- {
- mysql_mutex_destroy(&LOCK_alarm);
- mysql_cond_destroy(&COND_alarm);
- }
- }
- else
- mysql_mutex_unlock(&LOCK_alarm);
- }
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Remove another thread from the alarm
-*/
-
-void thr_alarm_kill(my_thread_id thread_id)
-{
- uint i;
- DBUG_ENTER("thr_alarm_kill");
-
- if (alarm_aborted)
- return;
- mysql_mutex_lock(&LOCK_alarm);
- for (i= queue_first_element(&alarm_queue) ;
- i <= queue_last_element(&alarm_queue);
- i++)
- {
- ALARM *element= (ALARM*) queue_element(&alarm_queue,i);
- if (element->thread_id == thread_id)
- {
- DBUG_PRINT("info", ("found thread; Killing it"));
- element->expire_time= 0;
- queue_replace(&alarm_queue, i);
- reschedule_alarms();
- break;
- }
- }
- mysql_mutex_unlock(&LOCK_alarm);
- DBUG_VOID_RETURN;
-}
-
-
-void thr_alarm_info(ALARM_INFO *info)
-{
- mysql_mutex_lock(&LOCK_alarm);
- info->next_alarm_time= 0;
- info->max_used_alarms= max_used_alarms;
- if ((info->active_alarms= alarm_queue.elements))
- {
- time_t now= my_time(0);
- long time_diff;
- ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
- time_diff= (long) (alarm_data->expire_time - now);
- info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
- }
- mysql_mutex_unlock(&LOCK_alarm);
-}
-
-/*
- This is here for thread to get interruptet from read/write/fcntl
- ARGSUSED
-*/
-
-
-static sig_handler thread_alarm(int sig __attribute__((unused)))
-{
-#ifdef MAIN
- printf("thread_alarm\n"); fflush(stdout);
-#endif
-#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
- my_sigset(sig,thread_alarm); /* int. thread system calls */
-#endif
-}
-
-
-#ifdef HAVE_TIMESPEC_TS_SEC
-#define tv_sec ts_sec
-#define tv_nsec ts_nsec
-#endif
-
-/* set up a alarm thread with uses 'sleep' to sleep between alarms */
-
-#ifdef USE_ALARM_THREAD
-static void *alarm_handler(void *arg __attribute__((unused)))
-{
- int error;
- struct timespec abstime;
-#ifdef MAIN
- puts("Starting alarm thread");
-#endif
- my_thread_init();
- alarm_thread_running= 1;
- mysql_mutex_lock(&LOCK_alarm);
- for (;;)
- {
- if (alarm_queue.elements)
- {
- time_t sleep_time,now= my_time(0);
- if (alarm_aborted)
- sleep_time=now+1;
- else
- sleep_time= ((ALARM*) queue_top(&alarm_queue))->expire_time;
- if (sleep_time > now)
- {
- abstime.tv_sec=sleep_time;
- abstime.tv_nsec=0;
- next_alarm_expire_time= sleep_time;
- if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) &&
- error != ETIME && error != ETIMEDOUT)
- {
-#ifdef MAIN
- printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n",
- error,errno);
-#endif
- }
- }
- }
- else if (alarm_aborted == -1)
- break;
- else
- {
- next_alarm_expire_time= ~ (time_t) 0;
- if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm)))
- {
-#ifdef MAIN
- printf("Got error: %d from ptread_cond_wait (errno: %d)\n",
- error,errno);
-#endif
- }
- }
- process_alarm(0);
- }
- bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
- alarm_thread_running= 0;
- mysql_cond_signal(&COND_alarm);
- mysql_mutex_unlock(&LOCK_alarm);
- pthread_exit(0);
- return 0; /* Impossible */
-}
-#endif /* USE_ALARM_THREAD */
-#endif
-
-/****************************************************************************
- Handling of test case (when compiled with -DMAIN)
-***************************************************************************/
-
-#ifdef MAIN
-#if !defined(DONT_USE_THR_ALARM)
-
-static mysql_cond_t COND_thread_count;
-static mysql_mutex_t LOCK_thread_count;
-static uint thread_count;
-
-#ifdef HPUX10
-typedef int * fd_set_ptr;
-#else
-typedef fd_set * fd_set_ptr;
-#endif /* HPUX10 */
-
-static void *test_thread(void *arg)
-{
- int i,param=*((int*) arg),wait_time,retry;
- time_t start_time;
- thr_alarm_t got_alarm;
- fd_set fd;
- FD_ZERO(&fd);
- my_thread_init();
- printf("Thread %d (%s) started\n",param,my_thread_name()); fflush(stdout);
- for (i=1 ; i <= 10 ; i++)
- {
- wait_time=param ? 11-i : i;
- start_time= my_time(0);
- if (thr_alarm(&got_alarm,wait_time,0))
- {
- printf("Thread: %s Alarms aborted\n",my_thread_name());
- break;
- }
- if (wait_time == 3)
- {
- printf("Thread: %s Simulation of no alarm needed\n",my_thread_name());
- fflush(stdout);
- }
- else
- {
- for (retry=0 ; !thr_got_alarm(&got_alarm) && retry < 10 ; retry++)
- {
- printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time);
- select(0,(fd_set_ptr) &fd,0,0,0);
- }
- if (!thr_got_alarm(&got_alarm))
- {
- printf("Thread: %s didn't get an alarm. Aborting!\n",
- my_thread_name());
- break;
- }
- if (wait_time == 7)
- { /* Simulate alarm-miss */
- fd_set readFDs;
- uint max_connection=fileno(stdin);
- FD_ZERO(&readFDs);
- FD_SET(max_connection,&readFDs);
- retry=0;
- for (;;)
- {
- printf("Thread: %s Simulating alarm miss\n",my_thread_name());
- fflush(stdout);
- if (select(max_connection+1, (fd_set_ptr) &readFDs,0,0,0) < 0)
- {
- if (errno == EINTR)
- break; /* Got new interrupt */
- printf("Got errno: %d from select. Retrying..\n",errno);
- if (retry++ >= 3)
- {
- printf("Warning: Interrupt of select() doesn't set errno!\n");
- break;
- }
- }
- else /* This shouldn't happen */
- {
- if (!FD_ISSET(max_connection,&readFDs))
- {
- printf("Select interrupted, but errno not set\n");
- fflush(stdout);
- if (retry++ >= 3)
- break;
- continue;
- }
- (void) getchar(); /* Somebody was playing */
- }
- }
- }
- }
- printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(),
- (int) (my_time(0)-start_time), wait_time); fflush(stdout);
- thr_end_alarm(&got_alarm);
- fflush(stdout);
- }
- mysql_mutex_lock(&LOCK_thread_count);
- thread_count--;
- mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */
- mysql_mutex_unlock(&LOCK_thread_count);
- my_thread_end();
- return 0;
-}
-
-
-static void *signal_hand(void *arg __attribute__((unused)))
-{
- sigset_t set;
- int sig,error,err_count=0;;
-
- my_thread_init();
- pthread_detach_this_thread();
- init_thr_alarm(10); /* Setup alarm handler */
- mysql_mutex_lock(&LOCK_thread_count); /* Required by bsdi */
- mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */
- mysql_mutex_unlock(&LOCK_thread_count);
-
- sigemptyset(&set); /* Catch all signals */
- sigaddset(&set,SIGINT);
- sigaddset(&set,SIGQUIT);
- sigaddset(&set,SIGTERM);
- sigaddset(&set,SIGHUP);
-#ifdef SIGTSTP
- sigaddset(&set,SIGTSTP);
-#endif
-#ifdef USE_ONE_SIGNAL_HAND
- sigaddset(&set,THR_SERVER_ALARM); /* For alarms */
- puts("Starting signal and alarm handling thread");
-#else
- puts("Starting signal handling thread");
-#endif
- printf("server alarm: %d thread alarm: %d\n",
- THR_SERVER_ALARM, thr_client_alarm);
- DBUG_PRINT("info",("Starting signal and alarm handling thread"));
- for(;;)
- {
- int code;
- while ((error=my_sigwait(&set,&sig,&code)) == EINTR)
- printf("sigwait restarted\n");
- if (error)
- {
- fprintf(stderr,"Got error %d from sigwait\n",error);
- if (err_count++ > 5)
- exit(1); /* Too many errors in test */
- continue;
- }
-#ifdef USE_ONE_SIGNAL_HAND
- if (sig != THR_SERVER_ALARM)
-#endif
- printf("Main thread: Got signal %d\n",sig);
- switch (sig) {
- case SIGINT:
- case SIGQUIT:
- case SIGTERM:
- case SIGHUP:
- printf("Aborting nicely\n");
- end_thr_alarm(0);
- break;
-#ifdef SIGTSTP
- case SIGTSTP:
- printf("Aborting\n");
- exit(1);
- return 0; /* Keep some compilers happy */
-#endif
-#ifdef USE_ONE_SIGNAL_HAND
- case THR_SERVER_ALARM:
- process_alarm(sig);
- break;
-#endif
- }
- }
-}
-
-
-int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
-{
- pthread_t tid;
- pthread_attr_t thr_attr;
- int i, param[2], error;
- sigset_t set;
- ALARM_INFO alarm_info;
- MY_INIT(argv[0]);
-
- if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
- {
- DBUG_PUSH(argv[1]+2);
- }
- mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
- mysql_cond_init(0, &COND_thread_count, NULL);
-
- /* Start a alarm handling thread */
- sigemptyset(&set);
- sigaddset(&set,SIGINT);
- sigaddset(&set,SIGQUIT);
- sigaddset(&set,SIGTERM);
- sigaddset(&set,SIGHUP);
- signal(SIGTERM,SIG_DFL); /* If it's blocked by parent */
-#ifdef SIGTSTP
- sigaddset(&set,SIGTSTP);
-#endif
- sigaddset(&set,THR_SERVER_ALARM);
- sigdelset(&set, thr_client_alarm);
- (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
-
- pthread_attr_init(&thr_attr);
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
- pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
- pthread_attr_setstacksize(&thr_attr,65536L);
-
- /* Start signal thread and wait for it to start */
- mysql_mutex_lock(&LOCK_thread_count);
- mysql_thread_create(0, &tid, &thr_attr, signal_hand, NULL);
- mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
- mysql_mutex_unlock(&LOCK_thread_count);
- DBUG_PRINT("info",("signal thread created"));
-
- pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
- printf("Main thread: %s\n",my_thread_name());
- for (i=0 ; i < 2 ; i++)
- {
- param[i]= i;
- mysql_mutex_lock(&LOCK_thread_count);
- if ((error= mysql_thread_create(0,
- &tid, &thr_attr, test_thread,
- (void*) &param[i])))
- {
- printf("Can't create thread %d, error: %d\n",i,error);
- exit(1);
- }
- thread_count++;
- mysql_mutex_unlock(&LOCK_thread_count);
- }
-
- pthread_attr_destroy(&thr_attr);
- mysql_mutex_lock(&LOCK_thread_count);
- thr_alarm_info(&alarm_info);
- printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
- alarm_info.active_alarms, alarm_info.max_used_alarms,
- alarm_info.next_alarm_time);
- while (thread_count)
- {
- mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
- if (thread_count == 1)
- {
- printf("Calling end_thr_alarm. This should cancel the last thread\n");
- end_thr_alarm(0);
- }
- }
- mysql_mutex_unlock(&LOCK_thread_count);
- thr_alarm_info(&alarm_info);
- end_thr_alarm(1);
- printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
- alarm_info.active_alarms, alarm_info.max_used_alarms,
- alarm_info.next_alarm_time);
- printf("Test succeeded\n");
- mysql_cond_destroy(&COND_thread_count);
- mysql_mutex_destroy(&LOCK_thread_count);
- my_end(MY_CHECK_ERROR);
- return 0;
-}
-
-#else /* !defined(DONT_USE_ALARM_THREAD) */
-
-int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
-{
- printf("thr_alarm disabled with DONT_USE_THR_ALARM\n");
- exit(1);
-}
-
-#endif /* !defined(DONT_USE_ALARM_THREAD) */
-#endif /* WIN */
-#endif /* MAIN */