The program below forks a child which calls gethostbyname. When using gdb
to debug it, the child seg faults in _dl_debug_state while calling
gethostbyname (run normally, it functions properly). See the comments
below for more information.
Thanks,
David
[This may actually be a glibc bug, so CC'd to bug-gcc. Not submitted to
Debian since it was also reproduced on a non-Debian build of gdb.]
/**
This program forks a child which calls gethostbyname. When using
gdb to debug it, the child seg faults in _dl_debug_state while
calling gethostbyname.
I have:
Linux 2.2.14
glibc 2.1.3
gdb 19990928 (Debian build)
This problem has been verified on another machine with Linux
2.2.14, glibc 2.1.2, and GDB 4.18.
To compile:
gcc -o test -g test.c
To duplicate bug:
gdb test
> set args localhost [or some other domainname]
> run
[child will now dump core]
> core core
Symbols already loaded for /lib/libc.so.6
Symbols already loaded for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
> bt
#0 0x4000a41d in _dl_debug_state () from /lib/ld-linux.so.2
#1 0x4000a125 in _dl_catch_error () from /lib/ld-linux.so.2
#2 0x400de4d0 in _dl_open () from /lib/libc.so.6
#3 0x400c2959 in __nss_configure_lookup () from /lib/libc.so.6
#4 0x4000a125 in _dl_catch_error () from /lib/ld-linux.so.2
#5 0x400c2911 in __nss_configure_lookup () from /lib/libc.so.6
#6 0x400c2cf8 in __nss_configure_lookup () from /lib/libc.so.6
#7 0x400c2737 in __nss_database_lookup () from /lib/libc.so.6
#8 0x400c376f in __nss_hosts_lookup () from /lib/libc.so.6
#9 0x400c5d44 in gethostbyname_r () from /lib/libc.so.6
#10 0x400c4d82 in gethostbyname () from /lib/libc.so.6
#11 0x8048895 in gnet_gethostbyname (hostname=0xbffffa36
"junglemonkey.net",
sa=0xbffff800) at test.c:176
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <dlfcn.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
int
main(int argc, char** argv)
{
pid_t pid;
if (argc != 2)
{
printf ("usage: %s <hostname>\n", argv[0]);
exit (EXIT_FAILURE);
}
/* Fork to do DNS look up. */
fork_again:
if ((pid = fork()) == 0)
{
struct hostent* he;
#if 0 /* This will also cause a seg fault. Compile with -ldl. */
if (!dlopen ("/lib/libnss_files.so.2", RTLD_NOW))
perror ("dlopen");
#endif
#if 0 /* This WON'T cause a seg fault. Compile with -ldl. */
if (!dlopen ("/lib/libm.so.6", RTLD_NOW))
perror ("dlopen");
#endif
he = gethostbyname(argv[1]);
/* Core dumped. This line not reached. */
_exit(EXIT_SUCCESS);
}
/* Read from the pipe */
else if (pid > 0)
{
/* Wait */
if (waitpid (pid, NULL, 0) == -1)
perror ("waitpid");
}
/* Try again */
else if (errno == EAGAIN)
{
sleep(0); /* Yield the processor */
goto fork_again;
}
/* Else there was an error */
else
{
perror ("fork");
}
exit (EXIT_SUCCESS);
return 0;
}