Hello,

I'm using pause() to suspend threads until I need them and pthread_kill(thread, SIGCONT) to resume. It works the first time over with the thread unpausing the first time I send SIGCONT, but not the second time around. Does sending the signal cause it to be ignored and if so, how do I reset it?

Thanks

Recommended Answers

All 9 Replies

To block threads you might want to try https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

Well I don't need to block, I need to pause from the child threads and unpause them from the main thread. I guess I could use blocking to pull it off, but why do I get the weird behaviour of it being able to pause and unpause once, but can't unpause afterward?

Let me know, thanks.

So blocking is looking really ugly for something that should easily be done with signals, any clue why sending sigcont the second time around cause trouble?

Can you post some code that I can run to reproduce you error? Otherwise I can fabricate something.

Can you post some code that I can run to reproduce you error? Otherwise I can fabricate something.

when child thread completes:
pause();

when main thread needs child to repeat routine (child thread is inf. loop):
pthread_kill(mThreadList, SIGCONT);

The main thread looks at an array of bool to see if all the child threads completed and before sending SIGCONT, I set all of them to false. Since neither assign values to the array at the same time, I didn't bother with blocking.

Since there's a lot going on in my code, writing a simple test case would be best.

This is working for me.

#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#define NUM_THREADS 2
pthread_t tid[NUM_THREADS];

void handler(int signum){
  // Empty
}
void *thrFunc(void *arg){
  long long id=(long long)arg;
  while(1) {
     printf("Pausing thread(%lld)\n",id);
     pause();
     printf("Working thread(%lld)\n",id);
  } 
  pthread_exit(0);
}

int main(){
  long long i;
  int err, id;
  char line[1024];
  struct sigaction act;
  act.sa_handler = handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  // Register signal and signal handler
  sigaction(SIGCONT, &act, NULL);
  for ( i=0; i < NUM_THREADS; i++) {
      err = pthread_create(&tid[i], NULL, thrFunc, (void *)(i+1));
      if (err != 0)
         printf("Error creating thread(%lld)\n",i);
  }
  do {
    sleep(1);
    printf("Enter thread to wake [1-%d]: ",NUM_THREADS);
    if (!fgets(line,sizeof(line),stdin)) 
        break;
    i = atoll(line);
    if ( i <= 0 || i > NUM_THREADS) 
      continue;
    printf("Waiting up thread(%lld)\n",--i);
    err = pthread_kill(tid[i],SIGCONT);
    if ( err ) {
       printf("Error: %s\n",strerror(err));
    }
  } while(1);
  printf("\nKilling\n");
  for ( i=0; i < NUM_THREADS; i++) {
      err = pthread_cancel(tid[i]);
      err = pthread_join(tid[i], NULL);
      if (err != 0)
         printf("Error joining thread(%lld)\n",i);
  }
  return 0;
}

Output:

$ gcc sigs.c -lpthread
$ ./a.out
Pausing thread(1)
Pausing thread(2)
Enter thread to wake [1-2]: 1
Waiting up thread(0)
Working thread(1)
Pausing thread(1)
Enter thread to wake [1-2]: 2
Waiting up thread(1)
Working thread(2)
Pausing thread(2)
Enter thread to wake [1-2]: 2
Waiting up thread(1)
Working thread(2)
Pausing thread(2)
Enter thread to wake [1-2]: 1
Waiting up thread(0)
Working thread(1)
Pausing thread(1)
Enter thread to wake [1-2]: ^D
Killing
$

This is working for me.

#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#define NUM_THREADS 2
pthread_t tid[NUM_THREADS];

void handler(int signum){
  // Empty
}
void *thrFunc(void *arg){
  long long id=(long long)arg;
  while(1) {
     printf("Pausing thread(%lld)\n",id);
     pause();
     printf("Working thread(%lld)\n",id);
  } 
  pthread_exit(0);
}

int main(){
  long long i;
  int err, id;
  char line[1024];
  struct sigaction act;
  act.sa_handler = handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  // Register signal and signal handler
  sigaction(SIGCONT, &act, NULL);
  for ( i=0; i < NUM_THREADS; i++) {
      err = pthread_create(&tid[i], NULL, thrFunc, (void *)(i+1));
      if (err != 0)
         printf("Error creating thread(%lld)\n",i);
  }
  do {
    sleep(1);
    printf("Enter thread to wake [1-%d]: ",NUM_THREADS);
    if (!fgets(line,sizeof(line),stdin)) 
        break;
    i = atoll(line);
    if ( i <= 0 || i > NUM_THREADS) 
      continue;
    printf("Waiting up thread(%lld)\n",--i);
    err = pthread_kill(tid[i],SIGCONT);
    if ( err ) {
       printf("Error: %s\n",strerror(err));
    }
  } while(1);
  printf("\nKilling\n");
  for ( i=0; i < NUM_THREADS; i++) {
      err = pthread_cancel(tid[i]);
      err = pthread_join(tid[i], NULL);
      if (err != 0)
         printf("Error joining thread(%lld)\n",i);
  }
  return 0;
}

Output:

$ gcc sigs.c -lpthread
$ ./a.out
Pausing thread(1)
Pausing thread(2)
Enter thread to wake [1-2]: 1
Waiting up thread(0)
Working thread(1)
Pausing thread(1)
Enter thread to wake [1-2]: 2
Waiting up thread(1)
Working thread(2)
Pausing thread(2)
Enter thread to wake [1-2]: 2
Waiting up thread(1)
Working thread(2)
Pausing thread(2)
Enter thread to wake [1-2]: 1
Waiting up thread(0)
Working thread(1)
Pausing thread(1)
Enter thread to wake [1-2]: ^D
Killing
$

Thanks, now it's going a few 100 rounds before I start seeing each thread halt. I'm writing a program that has each thread calculating a chunk of a wave, so now I see squares of it halting while others are still going, plus they're out of sync.

Adding sigaction did the job, which is odd since I thought changing the mask would be enough.

Thanks, now it's going a few 100 rounds before I start seeing each thread halt. I'm writing a program that has each thread calculating a chunk of a wave, so now I see squares of it halting while others are still going, plus they're out of sync.

Adding sigaction did the job, which is odd since I thought changing the mask would be enough.

Found the bug, totally unrelated to this problem... yay it work.

Good. I wasn't sure if you were still working the issue from you last last post. Just for reference I looked at some tool that we use and how they block/sleep theads, it uses semaphores (sem_wait and sem_post).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.