140 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * Copyright (c) 2021 OceanBase
 | 
						|
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
						|
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
						|
 * You may obtain a copy of Mulan PubL v2 at:
 | 
						|
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
						|
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
						|
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
						|
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
						|
 * See the Mulan PubL v2 for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#include <gtest/gtest.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <time.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include "share/ob_define.h"
 | 
						|
/*
 | 
						|
//signal function should not call I/O function and nother non-reentrant functions
 | 
						|
//this test would have a dead lock. Because localtime_r have a lock. When signal interrupt
 | 
						|
//occurs, if the main function get the lock and had not released it, the dead lock produced.
 | 
						|
void handler(int signum)
 | 
						|
{
 | 
						|
  char result[100];
 | 
						|
  time_t now;
 | 
						|
  struct tm time1;
 | 
						|
  now = time(NULL);
 | 
						|
  localtime_r(&now, &time1);
 | 
						|
  strftime(result, 100, "%T", &time1);
 | 
						|
  printf("At %s, user pressed Ctrl-C\n", result);
 | 
						|
}
 | 
						|
 | 
						|
int main (void)
 | 
						|
{
 | 
						|
  time_t now;
 | 
						|
  struct tm ltime;
 | 
						|
 | 
						|
  if (signal(SIGINT, handler) == SIG_IGN)
 | 
						|
    signal(SIGINT, SIG_IGN);
 | 
						|
 | 
						|
  now = time(NULL);
 | 
						|
  while(1) {
 | 
						|
    localtime_r(&now, <ime);
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
*/
 | 
						|
 | 
						|
namespace test {
 | 
						|
 | 
						|
bool g_run_test = false;
 | 
						|
void signal_handler(int signum)
 | 
						|
{
 | 
						|
  printf("singal num: %d", signum);
 | 
						|
  char result[100];
 | 
						|
  time_t now;
 | 
						|
  struct tm time1;
 | 
						|
  now = time(NULL);
 | 
						|
  localtime_r(&now, &time1);
 | 
						|
  strftime(result, 100, "%T", &time1);
 | 
						|
  printf("At %s, user pressed Ctrl-C\n", result);
 | 
						|
}
 | 
						|
 | 
						|
class ObSignalDealThread: public share::ObThreadPool
 | 
						|
{
 | 
						|
public:
 | 
						|
  virtual void run1();
 | 
						|
};
 | 
						|
 | 
						|
class ObSignalTest: public ::testing::Test
 | 
						|
{
 | 
						|
public:
 | 
						|
  void run_test();
 | 
						|
protected:
 | 
						|
  ObSignalDealThread signal_deal_thread_;
 | 
						|
};
 | 
						|
 | 
						|
void ObSignalDealThread::run(obsys::CThread *thread, void *arg)
 | 
						|
{
 | 
						|
 | 
						|
  UNUSED(arg);
 | 
						|
  sigset_t   waitset;
 | 
						|
  int        signum;
 | 
						|
  sigemptyset(&waitset);
 | 
						|
  sigaddset(&waitset, SIGINT);
 | 
						|
  struct timespec timeout = {1, 0};
 | 
						|
  while (!has_set_stop()) {
 | 
						|
    if ( -1 == (signum = sigtimedwait(&waitset, NULL, &timeout))) {
 | 
						|
      //do not log error, because timeout will also return -1.
 | 
						|
      printf("time out or error, errno=%d, errmsg=%m\n", errno);
 | 
						|
    } else {
 | 
						|
      printf("sigwaitinfo() fetch the signal: %d\n", signum);
 | 
						|
      signal_handler(signum);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ObSignalTest::run_test()
 | 
						|
{
 | 
						|
  if (g_run_test) {
 | 
						|
    //first sigmask in main thread
 | 
						|
    sigset_t bset, oset;
 | 
						|
    sigemptyset(&bset);
 | 
						|
    sigaddset(&bset, SIGINT);
 | 
						|
    if (pthread_sigmask(SIG_BLOCK, &bset, &oset) != 0)
 | 
						|
      printf("!! Set pthread mask failed\n");
 | 
						|
 | 
						|
    //second start signal deal thread
 | 
						|
    signal_deal_thread_.start();
 | 
						|
 | 
						|
    //loop call localtime_r
 | 
						|
    time_t now;
 | 
						|
    struct tm ltime;
 | 
						|
    now = time(NULL);
 | 
						|
    while(1) {
 | 
						|
      localtime_r(&now, <ime);
 | 
						|
    }
 | 
						|
    signal_deal_thread_.wait();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(ObSignalTest, signal_test)
 | 
						|
{
 | 
						|
  run_test();
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
//use ./test_signal_handle run
 | 
						|
int main(int argc, char **argv)
 | 
						|
{
 | 
						|
  ::testing::InitGoogleTest(&argc,argv);
 | 
						|
  if (argc >= 2) {
 | 
						|
    if (strcmp("run", argv[1]) ==0) {
 | 
						|
      ::test::g_run_test = true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return RUN_ALL_TESTS();
 | 
						|
}
 |