Home > front end >  Pause thread execution without using condition variable or other various synchronization pritmives
Pause thread execution without using condition variable or other various synchronization pritmives

Time:01-30

Problem

I wish to be able to pause the execution of a thread from a different thread. Note the thread paused should not have to cooperate. The pausing of the target thread does not have to occur as soon as the pauser thread wants to pause. Delaying the pausing is allowed.

I cannot seem to find any information on this, as all searches yielded me results that use condition variables...

Ideas

  • use the scheduler and kernel syscalls to stop the thread from being scheduled again
  • use debugger syscalls to stop the target thread

OS-agnostic is preferable, but not a requirement. This likely will be very OS-dependent, as messing with scheduling and threads is a pretty low-level operation.

CodePudding user response:

On a Unix-like OS, there's pthread_kill() which delivers a signal to a specified thread. You can arrange for that signal to have a handler which waits until told in some manner to resume.

Here's a simple example, where the "pause" just sleeps for a fixed time before resuming. Try on godbolt.

#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

void safe_print(const char *s) {
    int saved_errno = errno;
    if (write(1, s, strlen(s)) < 0) {
        exit(1);
    }
    errno = saved_errno;
}

void sleep_msec(int msec) {
    struct timespec t = {
                         .tv_sec = msec / 1000,
                         .tv_nsec = (msec % 1000) * 1000 * 1000
    };
    nanosleep(&t, NULL);
}

void *work(void *unused) {
    (void) unused;

    for (;;) {
        safe_print("I am running!\n");
        sleep_msec(100);
    }
    return NULL;
}

void handler(int sig) {
    (void) sig;
    safe_print("I am stopped.\n");
    sleep_msec(500);
}

int main(void) {

    pthread_t thr;
    pthread_create(&thr, NULL, work, NULL);

    sigset_t empty;
    sigemptyset(&empty);
    struct sigaction sa = {
                           .sa_handler = handler,
                           .sa_flags = 0,
    };
    sigemptyset(&sa.sa_mask);
    sigaction(SIGUSR1, &sa, NULL);

    for (int i = 0; i < 5; i  ) {
        sleep_msec(1000);
        pthread_kill(thr, SIGUSR1);
    }
    pthread_cancel(thr);
    pthread_join(thr, NULL);
    return 0;
}
  •  Tags:  
  • Related