1

My problem is that I cannot reuse cancelled pthread. Sample code:

#include <pthread.h>

pthread_t alg;
pthread_t stop_alg;
int thread_available;

void *stopAlgorithm() {
    while (1) {
        sleep(6);
        if (thread_available == 1) {
            pthread_cancel(alg);
            printf("Now it's dead!\n");
            thread_available = 0;
        }
    }
}
void *algorithm() {
    while (1) {
        printf("I'm here\n");
    }
}

int main() {
    thread_available = 0;
    pthread_create(&stop_alg, NULL, stopAlgorithm, 0);
    while (1) {
        sleep(1);
        if (thread_available == 0) {
            sleep(2);
            printf("Starting algorithm\n");
            pthread_create(&alg, NULL, algorithm, 0);
            thread_available = 1;
        }
    }
}

This sample should create two threads - one will be created at the program beginning and will try to cancel second as soon it starts, second should be rerunned as soon at it was cancelled and say "I'm here". But when algorithm thread cancelled once it doesn't start once again, it says "Starting algorithm" and does nothing, no "I'm here" messages any more. Could you please tell me the way to start cancelled(immediately stopped) thread once again?

UPD: So, thanks to your help I understood what is the problem. When I rerun algorithm thread it throws error 11:"The system lacked the necessary resources to create another thread, or the system-imposed limit on the total number of threads in a process PTHREAD_THREADS_MAX would be exceeded.". Actually I have 5 threads, but only one is cancelled, others stop by pthread_exit. So after algorithm stopped and program went to standby mode I checked status of all threads with pthread_join - all thread show 0(cancelled shows PTHREAD_CANCELED), as far as I can understand this means, that all threads stopped successfully. But one more try to run algorithm throws error 11 again. So I've checked memory usage. In standby mode before algorithm - 10428, during the algorithm, when all threads used - 2026m, in standby mode after algorithm stopped - 2019m. So even if threads stopped they still use memory, pthread_detach didn't help with this. Are there any other ways to clean-up after threads?

Also, sometimes on pthread_cancel my program crashes with "libgcc_s.so.1 must be installed for pthread_cancel to work"

PaulPonomarev
  • 355
  • 1
  • 4
  • 20
  • Cancel thread properly using cancellation points. Test functions return code and print the reason of failure. Ensure that thread_available variable access is synchronized. After fixing all these issues, if the problem still exists, post the code and program output. – Alex F Nov 24 '14 at 13:06
  • If I understood you right you're advising me to use stop_flag inside algorithm function. But then I should make those flags on each step, this is why I use pthread_cancel instead of exit – PaulPonomarev Nov 24 '14 at 13:24
  • What is the return value (and value of `errno`) on the second call to `pthread_start`? – Klas Lindbäck Nov 24 '14 at 13:26
  • 1
    I am not talking about flags. Read this: http://man7.org/linux/man-pages/man7/pthreads.7.html Cancellation points At least, add pthread_testcancel call to algorithm function and exit the loop if cancellation request is active. – Alex F Nov 24 '14 at 13:28
  • Or to be sure that thread cancelled I can wait until pthread_join status becomes "PTHREAD_CANCELLED". Thanks – PaulPonomarev Nov 24 '14 at 14:37

1 Answers1

0

Several points:

First, this is not safe:

int thread_available;

void *stopAlgorithm() {
    while (1) {
        sleep(6);
        if (thread_available == 1) {
            pthread_cancel(alg);
            printf("Now it's dead!\n");
            thread_available = 0;
        }
    }
}

It's not safe for at least reasons. Firstly, you've not marked thread_available as volatile. This means that the compiler can optimise stopAlgorithm to read the variable once, and never reread it. Secondly, you haven't ensured access to it is atomic, or protected it by a mutex. Either declare it:

volatile sig_atomic_t thread_available;

(or similar), or better, protect it by a mutex.

But for the general case of triggering one thread from another, you are better using a condition variable (and a mutex), using pthread_condwait or pthread_condtimedwait in the listening thread, and pthread_condbroadcast in the triggering thread.

Next, what's the point of the stopAlgorithm thread? All it does is cancel the algorithm thread after an unpredictable amount of time between 0 and 6 seconds? Why not just sent the pthread_cancel from the main thread?

Next, do you care where your algorithm is when it is cancelled? If not, just pthread_cancel it. If so (and anyway, I think it's far nicer), regularly check a flag (either atomic and volatile as above, or protected by a mutex) and pthread_exit if it's set. If your algorithm does big chunks every second or so, then check it then. If it does lots of tiny things, check it (say) every 1,000 operations so taking the mutex doesn't introduce a performance penalty.

Lastly, if you cancel a thread (or if it pthread_exits), the way you start it again is simply to call pthread_create again. It's then a new thread running the same code.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • The code I wrote above is only a example of my big programs part that interests me. Maybe I should have written more code as example. First thread is an algorithm, second is a failure check, so both of them cannot wait. If failure occurs algorithm should be stopped immediately at any step it is. And my problem was actually in last part of your answer - I cancel the thread, but when I try to create it again it doesn't launch, though thread_available is 0 and message about starting the algorithm appears – PaulPonomarev Nov 25 '14 at 09:01
  • Difficult to tell based on your example. Before you restart the thread, you should `pthread_join` the cancelled thread. Try that. – abligh Nov 25 '14 at 09:51
  • My comment was to big for this field, please read the UPD part – PaulPonomarev Nov 26 '14 at 15:31
  • A mutex is needed for the memory barrier. `volatile` [isn't](https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt) [enough](http://stackoverflow.com/q/1787450/132382). – pilcrow Nov 26 '14 at 16:17
  • I don't need a memory barrier, let it use as much as it needs, but free memory after threads finished or cancelled – PaulPonomarev Nov 27 '14 at 07:43
  • @PaulPonomarev I think this is was pilcrow means: http://en.wikipedia.org/wiki/Memory_barrier – abligh Nov 27 '14 at 13:47
  • Actually I understood what is happening. After I run my threads program takes part of memory, but it leaves it when threads finished and joined. I have joined all my threads on finish and after this I got constant memory usage, which also suits me. Next run of all threads use the same memory as previous without leak, so now I can run my algorithm as many times as I need. Thank you all! As @abligh answer includes many useful information about my problem I mark it as correct – PaulPonomarev Dec 02 '14 at 09:49