468,512 Members | 1,382 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,512 developers. It's quick & easy.

Incorrect time_t value from time() in signal handler

Hi,

I found a strange behaviour when using the time() function from time.h.
Sometimes when it is called, it does not show the correct time in
seconds, but an initial value. This time seem to be the time when the
program was started the first time.

My platform is a DEC machine with Tru64 onboard.

A possible explanation could be, that the time() function is called
within a signal handler. The program uses a SIGTIME to run regularly
through a procedure. There some log entries with time stamp are done.
These time stamps are sometimes wrong.

My question is, if someone knows, under which circumstances the time()
function can produce incorrect values and if there are some side
effects.

Thanks in advance,
Sven Bauhan

Aug 16 '06 #1
18 3237

Sven wrote:
Hi,

I found a strange behaviour when using the time() function from time.h.
Sometimes when it is called, it does not show the correct time in
seconds, but an initial value. This time seem to be the time when the
program was started the first time.

My platform is a DEC machine with Tru64 onboard.

A possible explanation could be, that the time() function is called
within a signal handler. The program uses a SIGTIME to run regularly
through a procedure. There some log entries with time stamp are done.
These time stamps are sometimes wrong.

My question is, if someone knows, under which circumstances the time()
function can produce incorrect values and if there are some side
effects.

Thanks in advance,
Sven Bauhan

not a C question per se, but :

Are you linking this with the thread-safe library? Anytime you have
asynchronous signals going off, you need a thread-safe (or actually,
reentrant-safe) program and library.

Also note that time() returns its value in a static location. If
you're doing this inside the timer signal function, you may be
overwriting the time value you got in other places.
Also are you checking the return value to see if it is returning an
error code ((time_t)-1) ??

Sometimes when you have signals going off, library routines and system
calls return INTERRUPTED_SYSTEM_CALL at random times. You have to
assume every call might fail, and check for failure. Many library and
system calls that don't fail normally can fail if you have timers going
off. Try disabling your timers and see if the time() problem goes
away. That would point you to this being a timer signal related
problem.

Aug 16 '06 #2
I have some problems with signal handling too.

Using a fprintf() call for tracing (of course with getting an
additional time information), the system (Fedora FC3) will get into a
deadlock situation, because the fprintf() will call an internal mutual
exclusion locking (mutex-operation). We got quite a similar situation
at SUN/solaris.

A good proposal is, never call any system function out of a signal
handler. Set a global flag or counter instead, and check the global
flag/counter at a main loop (if you have any).

I don't know, if the thread-safe functions can solve this problem.

Aug 16 '06 #3

Ancient_Hacker wrote:
Are you linking this with the thread-safe library? Anytime you have
asynchronous signals going off, you need a thread-safe (or actually,
reentrant-safe) program and library.
How do I have to do this? Is this just a linker option?
Also note that time() returns its value in a static location. If
you're doing this inside the timer signal function, you may be
overwriting the time value you got in other places.
That is no problem, I call:
time_t tVal;
time( &tVal );
Also are you checking the return value to see if it is returning an
error code ((time_t)-1) ??
I saw this, but what does ((time_t)-1) mean?
Is this the value given in the parameter decreased by one?
time_t tVal = 1;
if ( ! time( &tVal ) ) { /* error */ }

I cannot leave the timer away, because without the timer the program
would make no more sense.

Sven

Aug 16 '06 #4

Sven wrote:
How do I have to do this? Is this just a linker option?
it's often a compiler option, so it generates thread-sfe code and it
often passes on the name of the thread-safe library to the linker.
Look in your compiler and linker options for "thread safe"
I saw this, but what does ((time_t)-1) mean?
No, it's (-1) coerced into type size_t. A hobibble klooge, but it
works.

you want to write:
if( time( &val ) == ( (size_t) -1 ) ) { printf("time() failed!!, err
= %d\n", errno );

I cannot leave the timer away, because without the timer the program
would make no more sense.

well, you could call the timer function yourself from the main program,
in a loop. That would simulate everyting except the asynchronous
nature of the timer signals, which is what we want to try eliminating
as a suspect.

Aug 16 '06 #5
XSPD wrote:
I have some problems with signal handling too.

Using a fprintf() call for tracing (of course with getting an
additional time information), the system (Fedora FC3) will get into a
deadlock situation, because the fprintf() will call an internal mutual
exclusion locking (mutex-operation). We got quite a similar situation
at SUN/solaris.
A good proposal is, never call any system function out of a signal
handler. Set a global flag or counter instead, and check the global
flag/counter at a main loop (if you have any).

I don't know, if the thread-safe functions can solve this problem.
No. You can only call asynch-signal safe functions from within
a signal handler on posix platforms (which is offtopic here though, sorry).

http://www.opengroup.org/onlinepubs/...l#tag_02_04_03
lists the safe functions to call from a signal handler.
Aug 16 '06 #6
In article <11**********************@74g2000cwt.googlegroups. com>,
"Ancient_Hacker" <gr**@comcast.netwrote:
Sven wrote:
I saw this, but what does ((time_t)-1) mean?

No, it's (-1) coerced into type size_t. A hobibble klooge, but it
works.

Are time_t and size_t the same thing? Will casting -1 to size_t give
the same result as casting -1 to time_t?
Aug 16 '06 #7
In article <rt***************************@comcast.dca.giganew s.com>,
Rudolf <rt*****@bigfoot.comwrote:
>Are time_t and size_t the same thing?
No.
>Will casting -1 to size_t give
the same result as casting -1 to time_t?
That's platform dependant, but the answer is usually NO.

time_t is often a signed integral type, whereas size_t is always
unsigned.

time_t is often a 32 bit number, whereas there are several important
platforms where size_t is 64 bits.
--
Programming is what happens while you're busy making other plans.
Aug 16 '06 #8
"Ancient_Hacker" <gr**@comcast.netwrites:
[...]
Also note that time() returns its value in a static location. If
you're doing this inside the timer signal function, you may be
overwriting the time value you got in other places.
No it doesn't. time() returns a value of time time_t, which is an
arithmetic type. You can optionally pass it a non-null pointer to a
time_t object, to which it will store the same value.

If you're careless about the pointer value you pass to time(), you
could run into problems, but if you just call it as time(NULL) there's
no problem.

OP: You have a "#include <time.h>", right?

I've never heard of the time() function working incorrectly (unless
the system clock is set incorrectly). Could it be a bug in your
program?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 16 '06 #9
"Sven" <sv**@ast.dfs.dewrites:
Ancient_Hacker wrote:
[...]
>Also note that time() returns its value in a static location. If
you're doing this inside the timer signal function, you may be
overwriting the time value you got in other places.
That is no problem, I call:
time_t tVal;
time( &tVal );
The pointer argument to time() is a relic of ancient implementations.
It's simpler IMHO just to do:
tVal = time(NULL);
but either method will work.
>Also are you checking the return value to see if it is returning an
error code ((time_t)-1) ??
I saw this, but what does ((time_t)-1) mean?
Is this the value given in the parameter decreased by one?
time_t tVal = 1;
if ( ! time( &tVal ) ) { /* error */ }
No, it's the numeric value -1 converted to time_t. The "(time_t)" is
a cast operator, specifying the conversion.
I cannot leave the timer away, because without the timer the program
would make no more sense.
Calling time() is not one of the things that the C standard says you
can safely do from a signal handler. <OT>Your implementation may make
additional guarantees.</OT>

C99 7.14.1.1p5:

If the signal occurs other than as the result of calling the abort
or raise function, the behavior is undefined if the signal handler
refers to any object with static storage duration other than by
assigning a value to an object declared as volatile sig_atomic_t,
or the signal handler calls any function in the standard library
other than the abort function, the _Exit function, or the signal
function with the first argument equal to the signal number
corresponding to the signal that caused the invocation of the
handler. Furthermore, if such a call to the signal function
results in a SIG_ERR return, the value of errno is indeterminate.

The behavior you're apparently seeing, of time() returning an
incorrect value, is odd but permitted. If possible, set a flag in
your signal hanlder by assigning a value to a static object of type
volatile sig_atomic_t, and do all the other processing outside the
signal handler.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 16 '06 #10
"Ancient_Hacker" <gr**@comcast.netwrites:
Sven wrote:
[...]
>I saw this, but what does ((time_t)-1) mean?

No, it's (-1) coerced into type size_t. A hobibble klooge, but it
works.

you want to write:
if( time( &val ) == ( (size_t) -1 ) ) { printf("time() failed!!, err
= %d\n", errno );
The cast should be to time_t, not size_t.

For that matter, I don't think the cast is necessary (unless I'm
missing some subtle effect of type promotion).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 16 '06 #11
In article <11**********************@b28g2000cwb.googlegroups .com>,
Sven <sv**@ast.dfs.dewrote:
>I found a strange behaviour when using the time() function from time.h.
Sometimes when it is called, it does not show the correct time in
seconds, but an initial value.
>A possible explanation could be, that the time() function is called
within a signal handler. The program uses a SIGTIME to run regularly
through a procedure. There some log entries with time stamp are done.
These time stamps are sometimes wrong.
Your posting could be interpreted as indicating that the log entries
with time stamp are being generated by a system or library call
within the signal handler. If that is the case, then the results
are very much undefined according to the C standards, and the
calls are unsafe according to POSIX.1 .

According to the C standards, the only safe write operation inside a
signal handler is to change a variable of type volatile sig_atomic_t .
Also, according to the C standard, the only library call that is
certain to be safe within a signal handler is signal() itself.
In particular, the C standard offers no exemption for time() --
calling time() within a signal handler is undefined behaviour
according to the C standard.

POSIX.1 extends C to offer several other safe library calls within
signal handlers, specifically including time(). However, none
of the safe calls include any I/O at all.
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Aug 16 '06 #12
Rudolf <rt*****@bigfoot.comwrites:
In article <11**********************@74g2000cwt.googlegroups. com>,
"Ancient_Hacker" <gr**@comcast.netwrote:
>Sven wrote:
I saw this, but what does ((time_t)-1) mean?

No, it's (-1) coerced into type size_t. A hobibble klooge, but it
works.

Are time_t and size_t the same thing? Will casting -1 to size_t give
the same result as casting -1 to time_t?
They can be the same type, but there's no reason to assume that they
will be. I'm sure "size_t" was just a typo for "time_t".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 16 '06 #13

Keith Thompson wrote:
"Ancient_Hacker" <gr**@comcast.netwrites:
Sven wrote:
[...]
I saw this, but what does ((time_t)-1) mean?
No, it's (-1) coerced into type size_t. A hobibble klooge, but it
works.

you want to write:
if( time( &val ) == ( (size_t) -1 ) ) { printf("time() failed!!, err
= %d\n", errno );

The cast should be to time_t, not size_t.

For that matter, I don't think the cast is necessary (unless I'm
missing some subtle effect of type promotion).

Won't many compilers complain with a warning about "comparing signed
and unsigned types"? It's just a warning as at run-time the
bit-patterns are probably identical, but as you suggest, maybe in some
cases 16 bits of -1 get sometimes promoted to 65535 and doesnt compare
with a true -1. Been bitten by that many times.

Aug 16 '06 #14
Walter Roberson wrote:
....
POSIX.1 extends C to offer several other safe library calls within
signal handlers, specifically including time(). However, none
of the safe calls include any I/O at all.
Umm, the core POSIX file-descriptor-based I/O functions are
async-signal-safe, including open(), write(), read(), lseek(), and
close().

I don't have a link for the original POSIX.1 spec, but here's the list
for IEEE Std 1003.1, 2004:

http://www.opengroup.org/onlinepubs/...chap02_04.html

Philip Guenther

Aug 17 '06 #15
On 16 Aug 2006 17:09:11 -0700, "Philip Guenther" <gu******@gmail.com>
wrote in comp.lang.c:
Walter Roberson wrote:
...
POSIX.1 extends C to offer several other safe library calls within
signal handlers, specifically including time(). However, none
of the safe calls include any I/O at all.

Umm, the core POSIX file-descriptor-based I/O functions are
async-signal-safe, including open(), write(), read(), lseek(), and
close().
The core POSIX file descriptor based functions are not part of the C
language or library and are 100% off-topic here.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Aug 17 '06 #16
Keith Thompson wrote:
The behavior you're apparently seeing, of time() returning an
incorrect value, is odd but permitted. šIf possible, set a flag in
your signal hanlder by assigning a value to a static object of type
volatile sig_atomic_t, and do all the other processing outside the
signal handler.
I would think, that for a program (potentially) logging tons of lines per
second (such as a busy web-proxy or server), it is more efficient to set
the SIGALRM-handler to a function, that would update the static time_t
variable once per second.

That static variable could then be used by the logging function instead of
calling time() for every line logged many times per second (unless, of
course, the precision of the timestamp must be finer than a second).

Now, assuming that sig_atomic_t is as wide (or wider) as time_t, this can be
achieved by simply incrementing the variable once per second.

However, unless working on a RealTime OS, the signal may not, actually,
arrive at the exact time specified, and may, in fact, be delayed by many
seconds. So time() will need to be called at least occasionally to
readjust/catch up, if not every second -- as, I suspect, the original
poster is doing.

Syscalls are relatively expensive and software like web-proxies and
web-servers are frequently benchmarked -- even a small gain can make a
winner...

How can this be done (semi-)portably?

-mi
Aug 18 '06 #17
Mikhail Teterin <us****@aldan.algebra.comwrites:
Keith Thompson wrote:
>The behavior you're apparently seeing, of time() returning an
incorrect value, is odd but permitted. If possible, set a flag in
your signal hanlder by assigning a value to a static object of type
volatile sig_atomic_t, and do all the other processing outside the
signal handler.

I would think, that for a program (potentially) logging tons of lines per
second (such as a busy web-proxy or server), it is more efficient to set
the SIGALRM-handler to a function, that would update the static time_t
variable once per second.
Possibly, but SIGALRM isn't one of the signals guaranteed by the C
standard. (The ones guaranteed to exist are SIGABRT, SIGFPE, SIGILL,
SIGINT, SIGSEGV, and SIGTERM.)
That static variable could then be used by the logging function instead of
calling time() for every line logged many times per second (unless, of
course, the precision of the timestamp must be finer than a second).

Now, assuming that sig_atomic_t is as wide (or wider) as time_t, this can be
achieved by simply incrementing the variable once per second.
That's not guaranteed either. C99 7.18.3p3:

If sig_atomic_t (see 7.14) is defined as a signed integer type,
the value of SIG_ATOMIC_MIN shall be no greater than -127 and the
value of SIG_ATOMIC_MAX shall be no less than 127; otherwise,
sig_atomic_t is defined as an unsigned integer type, and the value
of SIG_ATOMIC_MIN shall be 0 and the value of SIG_ATOMIC_MAX shall
be no less than 255.

[...]
How can this be done (semi-)portably?
It probably can't, but I'm sure there are plenty of non-portable
solutions.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 18 '06 #18
In article <ln************@nuthaus.mib.org>
Keith Thompson <ks***@mib.orgwrote:
>The cast should be to time_t, not size_t.
[thus giving

time(&val) == (time_t)-1

for the test for failure.]
>For that matter, I don't think the cast is necessary (unless I'm
missing some subtle effect of type promotion).
In any "real" system, probably not. But suppose time_t is defined
"unsigned short", with USHRT_MAX being 4294967295, while INT_MAX
is 9223372036854775807. Then:

(USHRT_MAX)-1 == (time_t)-1

means:

(int)4294967295 == (int)4294967295

while:

(USHRT_MAX)-1 == -1

means:

(int)4294967295 == (int)-1

which is of course always false.

(Personally, I find the ANSI/ISO "value preserving" rules really
nasty, since they require a lot more case-by-case reasoning with
both Uxxx_MAX <= INT_MAX and Uxxx_MAX INT_MAX. In this case, I
think it works out the same anyway, though: with the "sensible"
rule -- in which unsigned-ness overrides -- instead of the Standard's
rule ("signed, unsigned, who can tell?") -- the last comparison
would be 4294967295U == 18446744073709551615U.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Aug 20 '06 #19

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Martin McCormick | last post: by
7 posts views Thread by Amit Sharma | last post: by
7 posts views Thread by Angus Comber | last post: by
4 posts views Thread by Pietro Cerutti | last post: by
45 posts views Thread by loudking | last post: by
1 post views Thread by =?Utf-8?B?R2Vvcmdl?= | last post: by
7 posts views Thread by Nick Keighley | last post: by
reply views Thread by NPC403 | last post: by
1 post views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.