NetBSD Problem Report #47703

From www@NetBSD.org  Thu Mar 28 16:12:00 2013
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
	by www.NetBSD.org (Postfix) with ESMTP id 5750C63F26F
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 28 Mar 2013 16:12:00 +0000 (UTC)
Message-Id: <20130328161159.0B96263F26F@www.NetBSD.org>
Date: Thu, 28 Mar 2013 16:11:58 +0000 (UTC)
From: oshima-ya@yagoto-urayama.jp
Reply-To: oshima-ya@yagoto-urayama.jp
To: gnats-bugs@NetBSD.org
Subject: pthread_cond_timedwait() does not wait after call pthread_condattr_setclock(CLOCK_MONOTONIC)
X-Send-Pr-Version: www-1.0

>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:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 28 16:15:00 +0000 2013
>Closed-Date:    Mon Oct 07 07:26:39 +0000 2013
>Last-Modified:  Sun Dec 11 10:05:01 +0000 2022
>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

>Release-Note:

>Audit-Trail:
From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47703 CVS commit: src/lib/libpthread
Date: Thu, 28 Mar 2013 14:07:12 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Thu Mar 28 18:07:12 UTC 2013

 Modified Files:
 	src/lib/libpthread: pthread_cond.c

 Log Message:
 PR/47703: Yasushi Oshima: pthread_cond_timedwait() does not wait
 after call pthread_condattr_setclock(CLOCK_MONOTONIC)

 _lwp_park(2) expects a realtime clock, and it gets passed a monotonic
 one.  Since monotonic < real, it never sleeps. This patch adjusts
 the monotonic clock to be a real one before it passes is to
 _lwp_park(2). This is the minimal hacky fix and it will be fixed
 properly in _lwp_park(2) in the future.

 XXX: pullup to 6.


 To generate a diff of this commit:
 cvs rdiff -u -r1.59 -r1.60 src/lib/libpthread/pthread_cond.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47703 CVS commit: src/tests/lib/libpthread
Date: Thu, 28 Mar 2013 14:50:02 -0400

 Module Name:	src
 Committed By:	christos
 Date:		Thu Mar 28 18:50:02 UTC 2013

 Modified Files:
 	src/tests/lib/libpthread: Makefile
 Added Files:
 	src/tests/lib/libpthread: t_condwait.c

 Log Message:
 Add pthread_cond_timedwait(3) test from PR/47703


 To generate a diff of this commit:
 cvs rdiff -u -r1.9 -r1.10 src/tests/lib/libpthread/Makefile
 cvs rdiff -u -r0 -r1.1 src/tests/lib/libpthread/t_condwait.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Manuel Bouyer" <bouyer@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47703 CVS commit: [netbsd-6] src/lib/libpthread
Date: Sat, 20 Apr 2013 15:14:08 +0000

 Module Name:	src
 Committed By:	bouyer
 Date:		Sat Apr 20 15:14:08 UTC 2013

 Modified Files:
 	src/lib/libpthread [netbsd-6]: pthread_cond.c

 Log Message:
 Pull up following revision(s) (requested by christos in ticket #862):
 	lib/libpthread/pthread_cond.c: revision 1.60
 	lib/libpthread/pthread_cond.c: revision 1.61
 PR/47703: Yasushi Oshima: pthread_cond_timedwait() does not wait
 after call pthread_condattr_setclock(CLOCK_MONOTONIC)
 _lwp_park(2) expects a realtime clock, and it gets passed a monotonic
 one.  Since monotonic < real, it never sleeps. This patch adjusts
 the monotonic clock to be a real one before it passes is to
 _lwp_park(2). This is the minimal hacky fix and it will be fixed
 properly in _lwp_park(2) in the future.
 XXX: pullup to 6.
 for safety, declare mono on the outermost block it is used.


 To generate a diff of this commit:
 cvs rdiff -u -r1.56.8.1 -r1.56.8.2 src/lib/libpthread/pthread_cond.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Mon, 07 Oct 2013 07:26:39 +0000
State-Changed-Why:
Committed and pulled up to netbsd-6.


From: "Robert Elz" <kre@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/47703 CVS commit: src/tests/lib/libpthread
Date: Sun, 11 Dec 2022 10:02:54 +0000

 Module Name:	src
 Committed By:	kre
 Date:		Sun Dec 11 10:02:53 UTC 2022

 Modified Files:
 	src/tests/lib/libpthread: t_condwait.c

 Log Message:
 This test makes (made) a false assumption about the way that
 process scheduling works.   That a process (or in this case,
 a thread) is no longer blocked at time T does not mean that it
 will resume execution at time T.   The OS is free to devote
 resources to other processes/threads instead - all we should
 normally be able to expect is that if it is not unblocked before
 time T, that it will not start running before then.

 In general though, the pthread_cond_*wait() functions don't guarantee
 even that - but for this test, the possibility of something else
 randomly signalling the condvar isn't believable, so don't worry about
 that possibility (but do fail without calling strerror(0) on the off
 chance it does happen).

 Once we cease testing that the process resumed running before some
 particular time, we can stop dealing with qemu timekeeping issues,
 it might (seem to) take qemu twice as long as was requested before
 the thread resumes, but that's OK - the same thing could happen on
 a loaded system for other reasons.

 Beyond that, the test also has (had) a race condition.   When using
 CLOCK_REALTIME though that clock needed to have advanced to T before
 the ETIMEDOUT should happen, there is no guarantee that it will stay >T
 (CLOCK_REALTIME is allowed to be reset backwards).   So, only test
 that the current time (after ETIMEDOUT) >= T when we're using
 CLOCK_MONOTONIC - for CLOCK_REALTIME the time might have stepped
 back between when the ETIMEDOUT happened and when the thread
 obtains the current clock reading.  For that case, all we can test
 is that the ETIMEDOUT actually happens.

 With much of what was there now gone, the code can be simplified,
 we no longer need to do timespec arithmetic, just one comparison
 (simpler to test that Tend >= Tstart+period than Tend-Tstart > period
 as we need Tstart+period for the abstime value for the timeout anyway).

 Note that this still tests for the issue reported in PR lib/47703
 which is where the test came from in the first place.

 ps: we seem to be missing pthread_cond_clockwait() which is the same
 as pthread_cond_timedwait() except that the clock to use is passed
 as a parameter, rather than as an attribute of the condition variable.


 To generate a diff of this commit:
 cvs rdiff -u -r1.9 -r1.10 src/tests/lib/libpthread/t_condwait.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: gnats-precook-prs,v 1.4 2018/12/21 14:20:20 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.