This is the mail archive of the libc-alpha@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: popen/pclose problem in Linux 2.2.x with vfork/glibc 2.1



Andreas said:

> Juergen Heinzl reported a bug in the implementation of popen/pclose to 
> the glibc maintainers.  Looking closer at the bug the problem might be 
> in the kernel since the test program runs fine with Linux 2.0.36 but
> fails with Linux 2.2.x.  The IMO significant difference is the vfork
> implementation in Linux 2.2 which popen uses with glibc 2.1.
> 
> Has anybody an idea what's broken ?
> 
> 
> Here are some parts of Juergen's reports (the full report is available
> via the bug database as PR 966 and 967 at
> http://www-gnats.gnu.org:8080/cgi-bin/wwwgnats.pl)

No idea about what's broken in the kernel.  I had expected the
following version of the test code to create havoc as well.  It doesn't
(on 2.2.4).  What else is glibc doing in popen() and vfork()?

Compile with "gcc -Wl,-Bstatic -Wall -g -o test test.c fork.S".

	-- Pete
extern void sleep(int);
extern int pipe(int p[2]);
extern int dup2(int, int);
extern int close(int);
extern int execl(const char *fmt, ...);
extern void printf(const char *fmt, ...);
extern int waitpid(int, int*, int);

int popen(const char *s);
void pclose(int pid, int val);
int fork(void);
int vfork(void);

int
main()
{
    int t, f;

    f = popen("/bin/false");
    sleep(1);
    t = popen("/bin/true");
    sleep(1);

    pclose(t, 0);
    pclose(f, 1);
    return 0;
}

int
popen(const char *cmd)
{
    int p[2], pid;
    register int ri;
    int i;

    ri = 3;
    i = 3;
    if (pipe(p) < 0) return -1;
    pid = vfork();
    if (pid < 0) return -1;
    if (pid == 0) {
	if (dup2(p[1], 1) < 0)
	    exit(127);
	close(p[0]);
	close(p[1]);
	ri++;
	i++;
	execl("/bin/sh", "sh", "-c", cmd, 0);
	exit(127);
    }

    close(p[1]);
    printf("ri = %d, i = %d\n", ri, i);
    return pid;
}

void
pclose(int pid, int val)
{
    int s;

    if (waitpid(pid, &s, 0) == -1) {
	printf("bad waitpid\n");
    } else {
	if (s & 0xff) {
	    printf("bad status\n");
	} else {
	    if (((s & 0xff00) >> 8) != val)
		printf("wanted %d, returned %04x\n", val, s);
	}
    }
}

.section .text
.globl fork
fork:
	movl $2, %eax
	int $0x80
	ret

.globl vfork
vfork:
	popl %ecx
	movl $190, %eax
	int $0x80
	jmp *%ecx
	ret

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]