Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pthread_cond_timedwait considered braindead.

139 views
Skip to first unread message

Mike Mowbray

unread,
Feb 7, 2002, 9:35:02 PM2/7/02
to
I have an application which is intolerant to backwards jumps in the
system time.

I'm now trying to change as much of the application code as possible
to behave better in the face of such backward time jumps.

The first step was to replace all calls to sleep() and nanosleep().
These calls do not actually sleep for the specified amount of physical
time, but rather operate using the system time in an absolute way.
So if the system time jumps backwards, these calls continue sleeping
for an unexpectedly long time. (I wonder how many apps exist out there
which use sleep() or nanosleep() naively without realizing that they'll
hang for long periods if ntpd or a sysadmin decides to step the systime
backwards.)

Anyway, I can change all such sleeps in my code to use
poll(0,0,timeout_msecs) - which seems to operate in terms of
physical time. [BTW, is there some other form of sleep I should
be using instead?]

Then I started analyzing what to do about pthread_cond_timedwait().
Its timespec arg is an absolute time. Therefore, one cannot perform
a pthread_cond_timedwait() that is guaranteed to wakeup up after a
certain amount of physical time has elapsed.

I'm unaware of any alternative pthread function which would allow
me to wait on a condvar for a specified physical time duration.
Does any such alternative exist?

If not, then it seems impossible in general to design a large class
of reasonable pthreads applications in such a way as to be robust
against backwards movements in the system time. E.g: various examples
in Dave Butenhof's pthreads book(*) will start behaving rather badly
(hanging), including especially the example of how to wait on a condvar.

(This is on Solaris 2.6, Solaris 8, and Tru64, in case that makes
any difference.)

- MikeM.

(*) I don't mean to single out Dave's book in particular - it just
happens to be the pthreads book that I always keep handy.

David Schwartz

unread,
Feb 7, 2002, 10:20:34 PM2/7/02
to
Mike Mowbray wrote:

> I have an application which is intolerant to backwards jumps in the
> system time.

Okay, so you know what to do, fix it so it's more tolerant.



> I'm now trying to change as much of the application code as possible
> to behave better in the face of such backward time jumps.

Perfect.



> The first step was to replace all calls to sleep() and nanosleep().
> These calls do not actually sleep for the specified amount of physical
> time, but rather operate using the system time in an absolute way.
> So if the system time jumps backwards, these calls continue sleeping
> for an unexpectedly long time. (I wonder how many apps exist out there
> which use sleep() or nanosleep() naively without realizing that they'll
> hang for long periods if ntpd or a sysadmin decides to step the systime
> backwards.)

Good, block instead on something that can be unblocked if there's a
time jump.



> Anyway, I can change all such sleeps in my code to use
> poll(0,0,timeout_msecs) - which seems to operate in terms of
> physical time. [BTW, is there some other form of sleep I should
> be using instead?]

You can do that, but you're really not assured that internally the
system won't just convert that to a future time.



> Then I started analyzing what to do about pthread_cond_timedwait().
> Its timespec arg is an absolute time. Therefore, one cannot perform
> a pthread_cond_timedwait() that is guaranteed to wakeup up after a
> certain amount of physical time has elapsed.

Sure you can.



> I'm unaware of any alternative pthread function which would allow
> me to wait on a condvar for a specified physical time duration.
> Does any such alternative exist?

Easy, when you detect a time jump, signal all condition variables. Keep
a linked list of them, or whatever makes the most sense in your
application.



> If not, then it seems impossible in general to design a large class
> of reasonable pthreads applications in such a way as to be robust
> against backwards movements in the system time. E.g: various examples
> in Dave Butenhof's pthreads book(*) will start behaving rather badly
> (hanging), including especially the example of how to wait on a condvar.

How many 'pthread_cond_timedwaits' do you have? That's a function you
shouldn't be using often at all. If there's nothing for you to do but
whatever the condition protects, use 'pthread_cond_wait'. If there's
something else to do that you could do, you should be doing it rather
than waiting.

Worker threads should block indefinitely until there's work for them to
do. If they need to go away, they should be explicitly woken by whatever
decided they need to go away. Good design everywhere will help minimize
this issue.

DS

Mike Mowbray

unread,
Feb 8, 2002, 12:07:08 AM2/8/02
to
David Schwartz wrote:

> > Mike Mowbray wrote:
>
> >> I have an application which is intolerant to backwards jumps

> >> in the system time. [...]

> >> Then I started analyzing what to do about pthread_cond_timedwait().
> >> Its timespec arg is an absolute time. Therefore, one cannot perform
> >> a pthread_cond_timedwait() that is guaranteed to wakeup up after a
> >> certain amount of physical time has elapsed.
>

> >> I'm unaware of any alternative pthread function which would
> >> allow me to wait on a condvar for a specified physical time
> >> duration. Does any such alternative exist?
>
> > Easy, when you detect a time jump, signal all condition variables.
> > Keep a linked list of them, or whatever makes the most sense in
> > your application.

This doesn't have the same semantics: pthread_cond_timedwait()
would no longer return ETIME to indicate a timeout.

But even ignoring that change of semantics, such an approach is
impractical for large-scale software...

It means that huge numbers of programmers around the world who
write pthreads-using code and who care about their applications
not hanging if the system time jumps backwards must design and
use such a linked-list-of-condvars library if they ever call
pthread_cond_timedwait(). Any software which fails to be designed
that way, and which must run for significant periods of time
is broken unless it has been designed that way. I don't believe
the designers of the pthreads standard intended such a thing.

The linked-list-of-condvars idea is a global solution to a
local problem. A programmer calling pthread_cond_timedwait()
often just wants to specify a timeout in physical time, not
some absolute absolute future systime. That's a local problem.
Global solutions to local problems have a way of failing to
scale up well.

Surely it would be far better to have an alternate standard way
of waiting on a condvar that used a physical timeout period
instead of an absolute expiry time? An individual programmer
could then directly express the exact desired semantics locally.


- MikeM.


Jeff Greif

unread,
Feb 8, 2002, 12:30:05 AM2/8/02
to
Trying to set a timeout interval rather than an absolute time is
sometimes useful, but is inherently unreliable in a multi-threaded
system, since the scheduling of other threads can cause an arbitrary
amount of time to go by between the call to the function with the
specified timeout and the actual system call that establishes the end of
the interval. This would be especially likely if you passed the timeout
value into a function (or nested functions) which called
pthread_cond_timedwait.

You basically can't get the 'physical time' interval you want, unless
you're lucky.

Jeff

"Mike Mowbray" <mi...@ot.com.au> wrote in message
news:3C635CFC...@ot.com.au...

Alexander Terekhov

unread,
Feb 8, 2002, 2:56:25 AM2/8/02
to

Mike Mowbray wrote:
[...]

> Surely it would be far better to have an alternate standard way
> of waiting on a condvar that used a physical timeout period
> instead of an absolute expiry time? An individual programmer
> could then directly express the exact desired semantics locally.

http://groups.google.com/groups?as_umsgid=LxpN7.2089%24RL6.63163%40news.cpqcorp.net
http://www.opengroup.org/onlinepubs/007904975/xrat/xsh_chap02.html#tag_03_02_08_19

regards,
alexander.

David Schwartz

unread,
Feb 8, 2002, 5:00:17 AM2/8/02
to
Mike Mowbray wrote:

> > > Easy, when you detect a time jump, signal all condition variables.
> > > Keep a linked list of them, or whatever makes the most sense in
> > > your application.

> This doesn't have the same semantics: pthread_cond_timedwait()
> would no longer return ETIME to indicate a timeout.

It shouldn't, it didn't time out. Obviously, the backwards jump would
occur before it timed out or it would have timed out already.



> But even ignoring that change of semantics, such an approach is
> impractical for large-scale software...

There is no change in semantics. Spurious wakeups are already allowed
by the standard.



> It means that huge numbers of programmers around the world who
> write pthreads-using code and who care about their applications
> not hanging if the system time jumps backwards must design and
> use such a linked-list-of-condvars library if they ever call
> pthread_cond_timedwait(). Any software which fails to be designed
> that way, and which must run for significant periods of time
> is broken unless it has been designed that way. I don't believe
> the designers of the pthreads standard intended such a thing.

Well, programmers shouldn't call pthread_cond_timedwait. They should
use thread libraries that already provide protection against such
problems. Write the protection into your thread wrapping library once
and you'll have it for every program you write from that day forward.
You shouldn't call pthread_cond_timedwait directly anyway -- how do you
port your code to non-pthreads platforms?



> The linked-list-of-condvars idea is a global solution to a
> local problem. A programmer calling pthread_cond_timedwait()
> often just wants to specify a timeout in physical time, not
> some absolute absolute future systime. That's a local problem.
> Global solutions to local problems have a way of failing to
> scale up well.

How many pthread_cond_timedwaits do you have? It's bad programming
practice to stall a thread if there's anything else it can do and no
reason to return if there's still nothing else to do. Whatever detects
that there is something to do can signal the thread.



> Surely it would be far better to have an alternate standard way
> of waiting on a condvar that used a physical timeout period
> instead of an absolute expiry time? An individual programmer
> could then directly express the exact desired semantics locally.

Do you want the semantics of not? If such a function returned at a
relative time, how could you call it in a loop? You'd get each wait for
the full timeout.

DS

David Butenhof

unread,
Feb 8, 2002, 8:24:02 AM2/8/02
to
Alexander Terekhov wrote:

For those who may not be sufficiently motivated to follow these links,
Alexander is subtly pointing out that we addressed this issue long ago in
POSIX, culminating in the release of the POSIX 1003.1d-1999 amendment;
which is part of POSIX 1003.1-2001 and the Single UNIX Specification, V3
(UNIX 2001).

These introduce the new (optional) "Monotonic clock" feature, allowing you
to apply a new system clock to condition variable waits and some others.
While you specify an ABSOLUTE time (so you don't need to worry about
recomputing delta times on subsequent iterations), the clock base is one
that can never be manually altered -- it ticks forward at a constant rate.

This is, however, an option. I am not currently aware that an
implementation exists anywhere. I certainly wouldn't hold out any great
hope that you'll find it widely available for several years.

/------------------[ David.B...@compaq.com ]------------------\
| Compaq Computer Corporation POSIX Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/

Alexander Terekhov

unread,
Feb 8, 2002, 9:05:52 AM2/8/02
to
David, it is not clear to me whether you see some problems
and/or dislike for some reason the *MONOTONIC CLOCK* option:

"2142 3.226 Monotonic Clock
2143 A clock whose value cannot be set via clock_settime()
and which cannot have negative clock
2144 jumps."

"13685 MON CLOCK_MONOTONIC
13686 The identifier for the system-wide monotonic clock,
which is defined as a
13687 clock whose value cannot be set via clock_settime()
and which cannot
13688 have backward clock jumps. The maximum possible clock
jump shall be
13689 implementation-defined."

"6615 MON If the Monotonic Clock option is supported,
all implementations shall support a clock_id of
6616 CLOCK_MONOTONIC defined in <time.h>. This clock
represents the monotonic clock for the
6617 system. For this clock, the value returned by
clock_gettime( ) represents the amount of time (in
6618 seconds and nanoseconds) since an unspecified point
in the past (for example, system start-up
6619 time, or the Epoch). This point does not change
after system start-up time. The value of the
6620 CLOCK_MONOTONIC clock cannot be set via clock_settime().
This function shall fail if it is
6621 invoked with a clock_id argument of CLOCK_MONOTONIC."

"32713 int pthread_condattr_getclock(
const pthread_condattr_t *restrict attr,
32714 clockid_t *restrict clock_id);
32715 int pthread_condattr_setclock(
pthread_condattr_t *attr,
32716 clockid_t clock_id);

<?>

regards,
alexander.

John Hickin

unread,
Feb 8, 2002, 9:01:40 AM2/8/02
to
David Butenhof wrote:

>
> This is, however, an option. I am not currently aware that an
> implementation exists anywhere. I certainly wouldn't hold out any great
> hope that you'll find it widely available for several years.
>

What is so difficult about this? Surely it is recognized that the lack
of a monotinic clock makes relative time waits difficult and that, in
turn makes asynchronous messaging a mess unless you don't care to use
timeouts on message sends.

The result is that you have to go through contortions to prevent
operators from changing the system time and you can't synch your system
time using NNTP. This causes other problems.

It is an unsatisfactory situation.


Regards, John.

Mark Johnson

unread,
Feb 8, 2002, 9:35:26 AM2/8/02
to

John Hickin wrote:
>
> David Butenhof wrote:
>
> >
> > This is, however, an option. I am not currently aware that an
> > implementation exists anywhere. I certainly wouldn't hold out any great
> > hope that you'll find it widely available for several years.
> >
>
> What is so difficult about this? Surely it is recognized that the lack
> of a monotinic clock makes relative time waits difficult and that, in
> turn makes asynchronous messaging a mess unless you don't care to use
> timeouts on message sends.
>

At the risk of starting a big flame war, there HAVE been several systems
that handled existing timers as relative to their original time (and not
to whatever the current system time is). I seem to recall VMS having
such a facility. There was quite a bit of discussion about that
particular "feature" in the system documentation [enough that I remember
it almost 15-20 years later]. Something to do with keeping network
message time out's sane....

Of course, what do you mean when you set up a timer? Is it...
- relative to local time [including standard and daylight time
changes]?
- relative to GMT?
- relative to the system clock?
- relative to the time since last reboot?
- must it be valid across reboot?
You can certainly make some generalizations but what I want for one
application is not the same for another. A network system needs
relatively small time out's that are insensitive to the reported system
time. A nightly batch job at 2am should run relative to local time. They
are all valid uses of the timer function.

> The result is that you have to go through contortions to prevent
> operators from changing the system time and you can't synch your system
> time using NNTP. This causes other problems.
>

No, I maintain that the application is broke. Unix tends to implement
one scheme well and leaves it up to the user to implement something more
general. If you don't like what is implemented, you are free to do what
you need to do to get the job done. That could include using another
system that implements what you are looking for.
--Mark

David Butenhof

unread,
Feb 8, 2002, 9:43:34 AM2/8/02
to
John Hickin wrote:

> David Butenhof wrote:
>
>> This is, however, an option. I am not currently aware that an
>> implementation exists anywhere. I certainly wouldn't hold out any great
>> hope that you'll find it widely available for several years.
>
> What is so difficult about this? Surely it is recognized that the lack
> of a monotinic clock makes relative time waits difficult and that, in
> turn makes asynchronous messaging a mess unless you don't care to use
> timeouts on message sends.

First, where did I say it was difficult? Gee, I don't see that word. I
merely stated the fact that you're not likely to see wide implementation
for a while. I didn't bother to try to give reasons, because it really
doesn't matter. The simple fact is that developers have lots of other
things to do, and never enough time or people to do it all. Therefore,
features and bugs get prioritized, and dealt with accordingly. New features
without which people have been happily and productively writing functioning
code for over 10 years rarely get to the top of that list quickly. Whether
or not you like that, it's an inevitable fact.

You are, of course, welcome to dig into the Linux, *BSD, or Darwin code,
and implement CLOCK_MONOTONIC yourself. Many people will thank you. (And as
many more will no doubt criticize your implementation choices, but that's
life.)

You're also welcome to suggest to your vendor(s) of choice that this is an
important feature for you, and you'd like to see it implemented soon. This
may or may not do you any good, since anyone who knows anything about the
thread standards probably already has it on their list. (See
"prioritization", above.)

> The result is that you have to go through contortions to prevent
> operators from changing the system time and you can't synch your system
> time using NNTP. This causes other problems.
>
> It is an unsatisfactory situation.

Although I hate to say it, I have to say that your arguments comes out to
essentially "it's not convenient to do what I want to do easily, therefore
the universe is busted".

I have no problem with you being unsatisfied; but either you have a problem
that you need to solve now, and you need to find a way to accomplish that,
or you would like to stand around arguing until someone else develops a
solution you can use. "Being unsatisfied" is of no particular value to you
or anyone else.

So: code it yourself, find another solution, or resign yourself to being
passively"unsatisfied" for quite a while. The choice, and responsibility,
is yours and yours alone.

David Schwartz

unread,
Feb 8, 2002, 3:40:27 PM2/8/02
to
Alexander Terekhov wrote:

> David, it is not clear to me whether you see some problems
> and/or dislike for some reason the *MONOTONIC CLOCK* option:

It's great where it's supported. It will solve a large subset of the
clock jump problems. However, there may also be some problems with
forward time jumps, which this doesn't address.

DS

0 new messages