How to detect an early exit from pthread_create without blocking for too long?

I have a stream named mainloop

i.e.

int run_mainloop;

void* mainloop(void* param)
{
    // local vars
    // initialize local vars

    while(run_mainloop)
    {
       // run mainloop
    }

    return 0;
}

The thread starts from a function with a name client_open, i.e.

int client_open()
{
    run_mainloop = 1;
    return pthread_create(&thread, NULL, mainloop, NULL);     
}

However, in mainloop, if the initialization of local variables failed, I need to immediately report client_openthe beginning of the exit.

pthread_joinnot suitable as it is blocking and I cannot have a block client_open. Had to wait a short time before returning, it would be okay.

How can I do this nicely without using pthread_join, which will block. I want to get a return code.

+5
source share
3 answers

pthread_tryjoin_np : pthread_create return , .

pthread_tryjoin_np , , , "a-ok", .

, , - : client_open , mainloop ( ).

+4

- .

. , , .

- ( ):

#include <pthread.h>

// Completion variable definition:    
typedef struct {
    pthread_mutex_t mtx;
    pthread_cond_t cnd;
    int completed;
    int return_code;
} Completion;

#define COMPLETION_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }

int completion_wait(Completion* c) { // add timeout if necessary
    pthread_mutex_lock(&c->mtx);
    while(!c->completed)
        pthread_cond_wait(&c->cnd, &c->mtx);
    int return_code = c->return_code;
    pthread_mutex_unlock(&c->mtx);
    return return_code;
}

void completion_signal(Completion* c, int return_code) {
    pthread_mutex_lock(&c->mtx);
    c->completed = 1;
    c->return_code = return_code;
    pthread_cond_signal(&c->cnd);
    pthread_mutex_unlock(&c->mtx);
}

// Usage:    

void* mainloop(void* vc) {
    int init_success = 0;
    // initialization
    // ...
    init_success = 1;

init_end:
    Completion* c = (Completion*)vc;
    completion_signal(c, init_success); // always signal
    if(!init_success)
        return NULL;

    // start the main loop
    return NULL;
}

int client_open()
{
    int run_mainloop = 1;
    pthread_t thread;
    Completion c = COMPLETION_INIT;
    pthread_create(&thread, NULL, mainloop, &c);
    pthread_detach(thread);
    return completion_wait(&c);
}
+4

, .

1) mainloop .

2) Linux pthread_tryjoin_np() pthread_timedjoin_np() , , . - , client_open() .

, @fge, . , , .


EDIT: Not such a good solution, but left here for reference. It would be better to signal to open with a variable condition that the initialization was in order.

3) Make sure run_mainloop is non-zero if there is one, and pthread_create will not work and the thread is started. If it is still zero after a while, then it does not start, so we call pthread_join to get the exit code.

int run_mainloop = 0;

void* mainloop(void* param)
{
    // init vars
    // if failure, exit early.

    // everything from this point on is good.
    run_mainloop = 1;
    while (run_mainloop))
    {
        // do styff
    }

    return 0;
}

int client_open()
{
    void* res;
    int rc = pthread_create(&g_thread_id, NULL, mainloop, NULL);
    if (rc != 0)
        return -1;

    usleep(100); // wait a little while, kinda dumb but allows time for init
    if (run_mainloop))
        return 0;

    pthread_join(g_thread_id, &res);
    return -1;
}
-1
source

All Articles