It appears that your program, at its core, it is doing this:

void
readproc(void *v)
{
    int fd;
    char buf[100];

    fd = (int)v;
    read(fd, buf, sizeof buf);
}

void
threadmain(int argc, char **argv)
{
    int p[2];

    pipe(p);
    proccreate(readproc, (void*)p[0], 8192);
    proccreate(readproc, (void*)p[1], 8192);
    close(p[0]);
    /* and here you expect the first readproc to be done */
    close(p[1]);
    /* and here the second */
}

Each read call is holding up a reference to its channel
inside the kernel, so that even though you've closed the fd
and removed the ref from the fd table, there is still a reference
to each side of the pipe in the form of the process blocked
on the read.

I've never been sure whether the implicit ref held during
the system call is good behavior, but it's hard to change.

In your case, writing 0 (or anything) makes the read
finish, releasing the last ref to the underlying pipe when
the system call finishes, and then everything cleans up
as expected.  So you've found your workaround, and now
we understand why it works.

Russ

Reply via email to