等待信号超时,如果收到信号则继续执行(没有与信号相关的动作)

时间:2017-12-11 12:04:29

标签: c pthreads signals

我试图等待超时信号。 我正在为分布式哈希表实现保持活动功能。服务器可以连接到其他服务器,它需要知道连接的服务器是否有问题并且不再连接。

这是第一个在服务器还活着时发送信号的函数。

void sendSignalKeepAlive(struct server *serverTable,unsigned int *serverCursor,struct server *s)
{
  for (size_t i = 0; i < *serverCursor; i++)
  {
    if( strcmp((char*)serverTable[i].ip,(char*)s->ip)==0 && serverTable[i].port==s->port)
    {
      pthread_kill(serverTable[i].keepAlive,SIGUSR1);
    }
  }
}

然后是与服务器关联的线程关联的另一个函数,它等待信号知道服务器是否处于活动状态。如果线程在定义的时间之前没有收到信号,则线程删除服务器然后结束。如果线程接收到信号,它将循环并等待另一个信号。

void *keepAlive(void *s)
{
  struct keepAliveThread *kat = (keepAliveThread*)s;

  //prepare the signal handler for our thread that will indicate that the server is alive, and prepare the timeout that indicate that the server is dead
  sigset_t mask;
    struct timespec timeout;
  sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);

  timeout.tv_sec = 10;
    timeout.tv_nsec = 0;


  while(1)
  {
    int sig = sigtimedwait(&mask, NULL, &timeout);
    printf("SIG VALUE%d\n",sig);
    if( sig < 0)
    {
        if (errno == EAGAIN) //timeout: the server is dead
        {
          printf("Timeout server with ip %s and port %u \n",kat->serv->ip,kat->serv->port);
                deleteServer(kat->serverTable,kat->serverCursor,kat->serv,kat->serverTableSize);
          pthread_cancel(pthread_self());
            }
    }
    else
    {
      printf("SIGNAL RECEIVED %d\n",sig);
      printf("Receive keep alive from server ip %s and port %u\n",kat->serv->ip,kat->serv->port);
    }
  }
}

有可能吗?我只想发送没有相关动作的信号,但我找不到如何做到这一点。

[更新] SIGUSR1给我用户定义信号1 然后它结束线程。我将SIGINFO的信号发送到本主题中显示的代码的SIGUSR1,我正在进行测试,我忘记在粘贴此主题之前更改它,对不起我的错误。但我仍然想知道是否有可能发送信号告诉我的线程继续执行而不结束它。

1 个答案:

答案 0 :(得分:0)

在线程keepAlive()中,你必须在while循环之前阻止线程等待使用pthread_sigmask(SIG_BLOCK, &mask, NULL);的信号。

如果信号未被阻止,则信号将在程序中具有默认行为,因此SIGUSR1将结束程序。

以下是一个例子:

#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>

pthread_t server1,server2,ka1,ka2;

void deleteServer(pthread_t server) {
  pthread_cancel(server);
}

void sendSignalKeepAlive(pthread_t server)
{
  pthread_kill(server,SIGUSR1);
}


void *keepAlive(void *s)
{
  pthread_t server = *((pthread_t*)s);

  char * servername;
  if(server == server1) servername = "server1";
  else if(server == server2) servername = "server2";

  sigset_t mask;
  sigemptyset (&mask);
  sigaddset (&mask, SIGUSR1);
  //////////////////////////////////////////////
  // Here SIGUSR1 is blocked for this thread:
  ////////////////////////////////////////////// 
  pthread_sigmask(SIG_BLOCK, &mask, NULL);

  struct timespec timeout;
  timeout.tv_sec = 10;
  timeout.tv_nsec = 0;


  while(1)
  {
    int sig = sigtimedwait(&mask, NULL, &timeout);
    printf("SIG VALUE%d\n",sig);
    if( sig < 0)
    {
        if (errno == EAGAIN) //timeout: the server is dead
        {
          printf("Timeout %s\n",servername);
                deleteServer(server);
          pthread_cancel(pthread_self());
            }
    }
    else
    {
      printf("SIGNAL RECEIVED %d\n",sig);
      printf("Receive keep alive from %s\n",servername);
    }
  }
}


void * server_thread( void * data) {
  while(1) {
    sleep(2);
    sendSignalKeepAlive(ka1);
    sendSignalKeepAlive(ka2);
  }
}


int main() {
  pthread_create(&server1,NULL,server_thread,NULL);
  pthread_create(&server2,NULL,server_thread,NULL);
  pthread_create(&ka1,NULL,keepAlive,&server1);
  pthread_create(&ka2,NULL,keepAlive,&server2);

  pthread_join(ka1,NULL);
  pthread_join(ka2,NULL);
  pthread_join(server1,NULL);
  pthread_join(server2,NULL);
}