Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Apr 2012 15:33:49 -0700
From:      Marcel Moolenaar <marcel@xcllnt.net>
To:        Dmitry Mikulin <dmitrym@juniper.net>
Cc:        toolchain@freebsd.org
Subject:   [GDB follow-fork] behavior change for wait()
Message-ID:  <7B7A25D1-E99D-486A-B1CA-A5CFEA837B81@xcllnt.net>

next in thread | raw e-mail | index | archive | help

--Apple-Mail=_043ECEEC-E8F4-47C1-8A83-5577BA74EA34
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

Hi Dmitry,

I've been testing the follow-fork changes in GDB and ran into some weird
behavior. Without gdb, my test program (attached) prints something like:

fbsdvm%	./fe=20
fe(41042): initial process. Doing fork & exec...
fe(41043): child after fork. Doing exec...
fe(41043): child after exec. Exiting...
fe(41042): child 41043 exited with status 0

In particular: the parent (pid=3D41042) calls wait(2) to reap the child =
and
the child exits with 0.

Under gdb, I see this:

fbsdvm%	gdb ./fe
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you =
are
welcome to change it and/or distribute copies of it under certain =
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for =
details.
This GDB was configured as "i386-marcel-freebsd"...
(gdb) br main
Breakpoint 1 at 0x80487b0: file fe.c, line 14.
(gdb) run
Starting program: /usr/home/marcel/fe=20

Breakpoint 1, main (argc=3DError accessing memory address 0x1: Bad =
address.
) at fe.c:14
14	{
(gdb) n
main (argc=3D1, argv=3D0xbfbfebb4) at fe.c:19
19		if (getenv("__FE_FORKED__") !=3D NULL) {
(gdb) c
Continuing.
fe(41141): initial process. Doing fork & exec...
[New process 41143]
fe(41143): child after fork. Doing exec...
fe(41143): child after exec. Exiting...
fe(41141): wait(2) failed with error 10 (No child processes)

Program exited normally.
(gdb)=20

When stepping at least once, the inferior will not be able to properly =
wait(2)
for its child as it seems to have been reaped already. I suspect this is =
done
by the debugger -- unintentionally at least.

Have you seen this before?

--=20
Marcel Moolenaar
marcel@xcllnt.net


--Apple-Mail=_043ECEEC-E8F4-47C1-8A83-5577BA74EA34
Content-Disposition: attachment;
	filename=fe.c
Content-Type: application/octet-stream;
	name="fe.c"
Content-Transfer-Encoding: 7bit

#include <sys/types.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char *newenv[] = { "__FE_FORKED__=yes", NULL };

int
main(int argc, char *argv[])
{
	int status;
	pid_t pid;

	/* Check if we exec'd ourselves after a fork. */
	if (getenv("__FE_FORKED__") != NULL) {
		printf("%s(%d): child after exec. Exiting...\n",
		    getprogname(), getpid());
		return (0);
	}

	printf("%s(%d): initial process. Doing fork & exec...\n",
	    getprogname(), getpid());

	pid = fork();
	switch (pid) {
	default:	/* parent */
		status = -1;
		pid = wait(&status);
		if (pid == -1)
			printf("%s(%d): wait(2) failed with error %d (%s)\n",
			    getprogname(), getpid(), errno, strerror(errno));
		else
			printf("%s(%d): child %d exited with status %d\n",
			    getprogname(), getpid(), pid, status);
		break;
	case 0:		/* child */
		printf("%s(%d): child after fork. Doing exec...\n",
		    getprogname(), getpid());
		setenv("__FE_FORKED__", "done", 1);
		execve(getprogname(), argv, newenv);
		err(2, "exec failed");
		break;
	case -1:
		err(1, "fork failed");
	}

	return (0);
}

--Apple-Mail=_043ECEEC-E8F4-47C1-8A83-5577BA74EA34--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?7B7A25D1-E99D-486A-B1CA-A5CFEA837B81>