This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
[Bug, 2.1.3] getlogin() can call alarm() but shouldn't.
- To: libc-alpha at sourceware dot cygnus dot com
- Subject: [Bug, 2.1.3] getlogin() can call alarm() but shouldn't.
- From: Jan Vroonhof <vroonhof at math dot ethz dot ch>
- Date: 07 Mar 2000 20:34:36 +0100
Version
This has been observed to occur in glibc 2.1.3.
Short Description
getlogin() can call alarm() but shouldn't
Symptoms
1. Applications are likely to loose
resolution and their timers will fail to restart.
2. XEmacs will crash when used with socks under glibc 2.1.3 with the
following back trace.
#10 0x8094ee4 in assert_failed (..
at /usr/local/src/XEmacs-21.2/src/emacs.c:2770
#11 0x81bde9d in alarm (howlong=0)
at /usr/local/src/XEmacs-21.2/src/signal.c:340
#12 0x4055045d in getutline_r () from /lib/libc.so.6
#14 0x40509b5d in getlogin () from /lib/libc.so.6
#15 0x400183c1 in lsEffUser () from /usr/local/lib/libsocks5_sh.so
#18 0x4002262f in connect () from /usr/local/lib/libsocks5_sh.so
#26 0x4051664b in getaddrinfo () from /lib/libc.so.6
#27 0x81d386d in init_system_name ()
at /usr/local/src/XEmacs-21.2/src/sysdep.c:2361
XEmacs uses itimers heavily and
reimplements alarm() (and setitimer) to make sure nobody calls it
inappropriately. Libraries that are known to use it are carefully
wrapped with code that manages the XEmacs timers. Unfortunately as
seen above, with socks any call to the network can potentially call
alarm.
Solutions
1. [prefered] Glibc should never mess with the SIGALRM timer
internally.
2. getitimer/setitimer should be used instead of alarm. This will
at least preserve more information.
Why is messing with the timer bad?
This from a message (from yours truly) previously posted to the XEmacs
use
Typical usage is, i.e. (this is also what is used in glibc).
old_timeout = alarm(0);
push new SIGALARM handler
alarm(our_time);
/* do your thing */
alarm(0);
pop SIGALARM handler
alarm(old_timeout);
The reason XEmacs overrides the alarm() functions is exactly to detect
stuff like this because it is often wrong
urysohn:/tmp> gcc testlarm.c [1]
urysohn:/tmp> ./a.out
value from alarm() was : 1
Restored to: 1.000000 s , should be 0.000500 s
Repeat to: 0.000000 s , should be 0.000700 s
So IMO this is a bug in glibc (should I file one?)
1. This really is a wart in the Unix API. The above code is only
correct if our_time << old_timeout (because it doesn't check for
the fact that the real timer could very well have expired). For that
reason it would be really nice if glibc would refrain from messing with
the timers, especially in stuff like get_login() where it is not
obvious.
2. If it really wants to mess with the timer (Don't the posix realtime
extensions now offer independent timers?), it should do so using
getitimer/setitimer because that doesn't loose precision and repeat
values.
Jan
Footnotes:
[1]
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
int main (int argc, char *argv[])
{
struct itimerval mydelay = {{0, 700} , {0,500}}; /* 500 msec, repeat 700 */
struct itimerval newdelay;
int inseconds;
if (setitimer(ITIMER_REAL,&mydelay,NULL))
{
perror("setimer: ");
exit(1);
}
inseconds = alarm(0);
alarm(inseconds);
getitimer(ITIMER_REAL,&newdelay);
alarm(0);
printf("value from alarm() was : %i\n",inseconds);
printf("Restored to: %li.%6.6li s , should be %li.%6.6li s\n",
newdelay.it_value.tv_sec, newdelay.it_value.tv_usec,
mydelay.it_value.tv_sec, mydelay.it_value.tv_usec);
printf("Repeat to: %li.%6.6li s , should be %li.%6.6li s\n",
newdelay.it_interval.tv_sec, newdelay.it_interval.tv_usec,
mydelay.it_interval.tv_sec, mydelay.it_interval.tv_usec);
}