LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Failed to make error EINTR with pthread_kill, but succeed with kill (https://www.linuxquestions.org/questions/programming-9/failed-to-make-error-eintr-with-pthread_kill-but-succeed-with-kill-4175535934/)

sisrnb 03-06-2015 06:18 AM

Failed to make error EINTR with pthread_kill, but succeed with kill
 
To do unit test, I want to make sem_wait get error EINTR.
I've written a program below:
Code:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

#define PRINTF(fmt, ...)  printf("%s:%d: " fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define WAIT_INTERVAL      1000

static sem_t sem;

static void sig_handler_drp(int sig)
{
  if (SIGUSR1 == sig)
  {
      PRINTF("SIGUSR1 received\n");
  }
}
void *thread_drp(void *arg)
{
  usleep(WAIT_INTERVAL);
  if (kill(getpid(), SIGUSR1))
  {
      PRINTF("ERROR! kill\n");
  }
//  if (pthread_kill(*(pthread_t *)arg, SIGUSR1))
//  {
//      PRINTF("ERROR! pthread_kill\n");
//  }
  return NULL;
}
int main(int argc, char ** argv)
{
  struct sigaction sa;
  pthread_t tid;

  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = sig_handler_drp;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (-1 == sigaction(SIGUSR1, &sa, NULL))
  {
      PRINTF("ERROR! sigaction\n");
  }
  if (sem_init(&sem, 0, 0))
  {
      PRINTF("ERROR! sem_init\n");
  }
  if (pthread_create(&tid, NULL, thread_drp, &tid))
  {
      PRINTF("ERROR! pthread_create\n");
  }

  if (sem_wait(&sem))
  {
      PRINTF("ERROR! sem_wait\n");
      if (EINTR == errno)
      {
        PRINTF("ERROR! sem_wait gets EINTR\n");
      }
  }

  if (pthread_join(tid, NULL))
  {
      PRINTF("ERROR! pthread_join\n");
  }
  if (sem_destroy(&sem))
  {
      PRINTF("ERROR! sem_destroy\n");
  }

  return 0;
}

The output of the program is:
Code:

sig_handler_drp:19: SIGUSR1 received
main:59: ERROR! sem_wait
main:62: ERROR! sem_wait gets EINTR

If I use pthread_kill instead of kill in function thread_drp,
the program will get stuck by sem_wait.
Why I can't make error EINTR with pthread_kill?

NevemTeve 03-06-2015 08:04 AM

Why did you expect you could?

Anyways, change this:

Code:

old:  PRINTF("ERROR! sem_wait\n");
new:  PRINTF("ERROR! sem_wait errno=d: %s\n", errno, strerror (errno));


sisrnb 03-06-2015 08:27 AM

Quote:

Originally Posted by NevemTeve (Post 5327812)
Why did you expect you could?

Anyways, change this:

Code:

old:  PRINTF("ERROR! sem_wait\n");
new:  PRINTF("ERROR! sem_wait errno=d: s\n", errno, strerror (errno));


In my apprehension, using kill() may sometimes affect other threads in the process, but pthread_kill() doesn't.
Maybe I was wrong. :)
Is that possible with pthread_kill()?

Wow, using strerror() is amazing! Thanks!

SoftSprocket 03-06-2015 10:51 AM

Did you read the man page for pthread_kill? You are sending a signal to the thread that is calling pthread_kill and then exiting. While signal handlers are shared pthread_kill only signals the thread whose id is passed. In other words your program is behaving the way it should.

Here is a signal going both ways -all error checking absent and not ready for prime time:
Code:

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

sig_atomic_t ok = 1;

void handle_sig (int i) {
        ok = 0;
}

void* th (void* arg) {
        int i = 0;
        while (ok) {
                sleep (1);
                printf ("d\n", ++i);
                if (arg != NULL) {
                        printf ("sending d\n", SIGUSR1);
                        pthread_kill (*(pthread_t*)arg, SIGUSR1);
                }
        }

        printf ("Exiting\n");
        return arg;
}

int main () {
        signal (SIGUSR1, handle_sig);

        pthread_t tid;
       
        pthread_create (&tid, NULL, th, NULL);

        sleep (5);
        printf ("sending d\n", SIGUSR1);
        pthread_kill (tid, SIGUSR1);
        pthread_join (tid, NULL);

        ok = 1;
        pthread_t pid = getpid ();
        pthread_create (&tid, NULL, th, &pid);
       
        sleep (5);
        pthread_join (tid, NULL);

        printf ("Goodbye\n");


        return 0;
}

It interrupts the thread then sets up another and tries to kill the parent but this causes a sigfault, which I suspect is because you can't signal the parent this way.

sisrnb 03-09-2015 09:30 AM

Quote:

Originally Posted by SoftSprocket (Post 5327894)
You are sending a signal to the thread that is calling pthread_kill and then exiting.

I meant to send signal to thread main and I thought I was sending to thread main.
Thanks for your reply! Now I've changed the 4th parameter of pthread_create to '&tid_main' which value is given by running pthread_self() in function main, and it works fine.
My program is changed to:
Code:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

#define PRINTF(fmt, ...)  printf("%s:%d: " fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define WAIT_INTERVAL      1000

static sem_t sem;

static void sig_handler_drp(int sig)
{
  if (SIGUSR1 == sig)
  {
      PRINTF("SIGUSR1 received\n");
  }
}
void *thread_drp(void *arg)
{
  usleep(WAIT_INTERVAL);
//  if (kill(getpid(), SIGUSR1))
//  {
//      PRINTF("ERROR! kill\n");
//  }
  if (pthread_kill(*(pthread_t *)arg, SIGUSR1))
  {
      PRINTF("ERROR! pthread_kill\n");
  }
  return NULL;
}
int main(int argc, char ** argv)
{
  struct sigaction sa;
  pthread_t tid;
  pthread_t tid_self = pthread_self();

  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = sig_handler_drp;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (-1 == sigaction(SIGUSR1, &sa, NULL))
  {
      PRINTF("ERROR! sigaction\n");
  }
  if (sem_init(&sem, 0, 0))
  {
      PRINTF("ERROR! sem_init\n");
  }
  if (pthread_create(&tid, NULL, thread_drp, &tid_self))
  {
      PRINTF("ERROR! pthread_create\n");
  }

  if (sem_wait(&sem))
  {
      //PRINTF("ERROR! sem_wait\n");
      PRINTF("ERROR! sem_wait errno=%d: %s\n", errno, strerror (errno));
      if (EINTR == errno)
      {
        PRINTF("ERROR! sem_wait gets EINTR\n");
      }
  }

  if (pthread_join(tid, NULL))
  {
      PRINTF("ERROR! pthread_join\n");
  }
  if (sem_destroy(&sem))
  {
      PRINTF("ERROR! sem_destroy\n");
  }

  return 0;
}



All times are GMT -5. The time now is 10:58 AM.