Domanda

Sto riscontrando uno strano problema. Ho il seguente codice:

    dbg("condwait: timeout = %d, %d\n", 
        abs_timeout->tv_sec, abs_timeout->tv_nsec);
    ret = pthread_cond_timedwait( &q->q_cond, &q->q_mtx, abs_timeout );
    if (ret == ETIMEDOUT)
    {
      dbg("cond timed out\n");
      return -ETIMEDOUT;
    }

dbg chiama gettimeofday prima di ogni linea e antepone la linea con l'ora. Il risultato è il seguente output:

    7.991151: condwait: timeout = 5, 705032704
    7.991158: cond timed out

Come puoi vedere, tra le due righe di debug sono passati solo 7 microsecondi, ma pthread_cond_timedwait ha restituito ETIMEDOUT. Come può succedere? Ho anche provato a impostare l'orologio su qualcos'altro durante l'inizializzazione della variabile cond:

int ret;
ret = pthread_condattr_init(&attributes);
if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret);
ret = pthread_condattr_setclock(&attributes, CLOCK_REALTIME);
if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret);
ret = pthread_cond_init( &q->q_cond, &attributes );
if (ret != 0) printf("COND INIT FAILED: %d\n", ret);

(nessuno dei messaggi di errore viene stampato). Ho provato sia CLOCK_REALTIME che CLOCK_MONOTONIC.

Questo codice fa parte di una coda di blocco. Ho bisogno di funzionalità tali che se non si inserisce nulla in questa coda in 5 secondi, succede qualcos'altro. Il mutex e il cond sono entrambi inizializzati, poiché la coda di blocco funziona bene se non uso <=>.

È stato utile?

Soluzione

pthread_cond_timedwait richiede un tempo assoluto, non un tempo relativo. Devi rendere assoluto il tuo tempo di attesa aggiungendo l'ora corrente al tuo valore di timeout.

Altri suggerimenti

L'overflow in timespec è in genere il colpevole di strani timeout.
Cerca EINVAL:

void timespec_add(struct timespec* a, struct timespec* b, struct timespec* out)
{
    time_t sec = a->tv_sec + b->tv_sec;
    long nsec = a->tv_nsec + b->tv_nsec;

    sec += nsec / 1000000000L;
    nsec = nsec % 1000000000L;

    out->tv_sec = sec;
    out->tv_nsec = nsec;
}

La variabile condizione può sbloccarsi in modo spurio. È necessario controllarlo in un ciclo e controllare la condizione ogni volta. Probabilmente dovrai aggiornare anche il valore di timeout.

Ho trovato della documentazione per pthread_cond_timedwait qui .

  

Quando si usano variabili di condizione lì   è sempre un predicato booleano   coinvolgendo variabili condivise associate   con ogni condizione attendere che sia vero   se il thread dovesse procedere. spurie   sveglia dal   pthread_cond_timedwait () o   Le funzioni pthread_cond_wait () possono   si verificano. Dal momento che il ritorno da   pthread_cond_timedwait () o   pthread_cond_wait () non implica   qualcosa sul valore di questo   predicato, il predicato dovrebbe essere   rivalutato su tale ritorno.

Come già indicato in altre risposte, devi usare il tempo assoluto. Da C11 puoi usare timespec_get().

struct timespec time;
timespec_get(&time, TIME_UTC);
time.tv_sec += 5;

pthread_cond_timedwait(&cond, &mutex, &time);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top