NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/47703: pthread_cond_timedwait() does not wait after call pthread_condattr_setclock(CLOCK_MONOTONIC)



>Number:         47703
>Category:       lib
>Synopsis:       pthread_cond_timedwait() does not wait after call 
>pthread_condattr_setclock(CLOCK_MONOTONIC)
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 28 16:15:00 +0000 2013
>Originator:     Yasushi Oshima
>Release:        6.1_RC2
>Organization:
>Environment:
NetBSD hassaku 6.1_RC2 NetBSD 6.1_RC2 (GENERIC) #1: Mon Mar 18 08:10:25 JST 
2013  oshima@bergamot:/export/netbsd-6/obj/amd64/sys/arch/amd64/compile/GENERIC 
amd64

>Description:
pthread_cond_timedwait() does not wait after call 
pthread_condattr_setclock(CLOCK_MONOTONIC).

This is a result of a test code (see How To Repeat) which call 
pthread_cond_timedwait() set to 10sec:

**** REALTIME clock wait starting
STARTTIME:  1364483493.092059685 sec
TIMEDOUTED: 1364483503.112246279 sec
ELAPSED   : 10.020186594 sec
**** REALTIME clock wait ended

**** MONOTONIC clock wait starting
STARTTIME:  508074.001066903 sec
TIMEDOUTED: 508074.001109810 sec
ELAPSED   : 0.000042907 sec
**** MONOTONIC clock wait ended

in MONOTONIC, this returned with TIMEDOUTED after only 0.00004sec even setting 
as 10sec.

This occurs on both NetBSD 6.1_RC2 and NetBSD-current.

And,
 pkgsrc/lang/ruby193-base uses MONOTONIC clock like this.
 Some application program of ruby (for example, pkgsrc/net/mikutter) can't 
sleep, CPU load becomes 100%.
>How-To-Repeat:
Execute following test code:

#include <err.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define WAITTIME 10     /* Timeout wait secound */

void *test_thread(void *param)
{
        struct timespec ts, to, te;
        clockid_t clck;
        pthread_condattr_t attr;
        pthread_cond_t cond;
        pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
        int sec, nsec;
        int ret=0;

        clck= *(clockid_t *)param;
        pthread_condattr_init(&attr);
        pthread_condattr_setclock(&attr, clck); /* REALTIME or MONOTONIC */
        pthread_cond_init(&cond, &attr);

        if ((ret = pthread_mutex_lock(&m))) {
                fprintf(stderr, "pthread_mutex_lock: %s\n",strerror(ret));
                pthread_exit(&ret);
        }

        clock_gettime(clck, &ts);       /* get now */
        to = ts;
        printf("STARTTIME:  %ld.%09ld sec\n", to.tv_sec, to.tv_nsec);
        ts.tv_sec += WAITTIME;  /* Timeout wait */
        if ((ret = pthread_cond_timedwait(&cond, &m, &ts))) {
                if (ret == ETIMEDOUT) {
                        /* Timeout */
                        clock_gettime(clck, &te);
                        sec = te.tv_sec-to.tv_sec;
                        nsec = te.tv_nsec-to.tv_nsec;
                        if ( nsec < -1 ) {
                                nsec+=1000*1000*1000;
                                sec-=1;
                        }
                        fprintf(stderr,"TIMEDOUTED: %ld.%09ld sec\n", 
te.tv_sec, te.tv_nsec);
                        fprintf(stderr,"ELAPSED   : %d.%09d sec\n",  sec, nsec);
                } else {
                        fprintf(stderr, "pthread_cond_timedout: 
%s\n",strerror(ret));
                        pthread_exit(&ret);
                }
        }
        if ((ret = pthread_mutex_unlock(&m))) {
                fprintf(stderr, "pthread_mutex_unlock: %s\n",strerror(ret));
                pthread_exit(&ret);
        }
        pthread_exit(&ret);
}

int main(int argc, char* argv[]){
        pthread_t child_thread;
        clockid_t clck;
        /*
         * REALTIME clock thread wait
         */
        clck = CLOCK_REALTIME;
        printf( "**** REALTIME clock wait starting\n");
        if (pthread_create(&child_thread, NULL, test_thread, &clck)!=0)
                err(1,"pthread_create");
        if( pthread_join(child_thread, NULL)!=0) /* wait for terminate */
                err(1,"pthread_join");
        printf( "**** REALTIME clock wait ended\n");
        printf( "\n");
        /*
         * MONOTONIC clock thread wait
         */
        clck = CLOCK_MONOTONIC;
        printf( "**** MONOTONIC clock wait starting\n");
        if (pthread_create(&child_thread, NULL, test_thread, &clck)!=0)
                err(1,"pthread_create");
        if( pthread_join(child_thread, NULL)!=0) /* wait for terminate */
                err(1,"pthread_join");
        printf( "**** MONOTONIC clock wait ended\n");
        return 0;
}

>Fix:
I don't know



Home | Main Index | Thread Index | Old Index