[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

package menu possible fix



Hello!

Some days ago i wrote that he package menu does not create the 
menu structures for e.g. twm.

Now i found out why.

The version of menu i used is: menu-2.1.5
In update-menus.cc is at line 607 the following code:


 close(fds[1]);
 close(0);
 dup(fds[0]);

 //???
 // The next 2 lines seem strange! But if I leave it out,
 // pipes (in commands executed in the /etc/menu-method/* scripts as
 // postrun etc) don't work when ran from dpkg. (When run from dpkg,
 // we elsewhere close all filedescriptors. And apparently
 // we need STDOUT open somehow in order to make the pipes work.
 close(1);
 dup(fds[0]);

this is part of a child process which executes the skripts for the
menu generation.
What it does is to close the write end of a pipe to the parent
and dup the read end to stdin and stdout.

It seems to dup to stdout because dpkg cant handle the output
of the child which occurs if he doesnt dup to stdout
(couldnt test)

In the parent we have the following:
close(fds[0]);
write something to fds[1]
close(fds[1]);

And here is the problem. The child writes to a pipe
which has the read and write end in the parent closed.
(What i dont understand is that the code worked at all
because the child writes to the read end of the pipe not the 
write end)

And there is something i really dont understand.
If we only close fd[0] the read end in the parent everything
works. No SIGPIPE as should be. Only after closing the write
end we get a signal.

And the behavior is different between hurd and linux.
Linux runs happily and Hurd kills the child.
This can be seen in the source attached below.

And here my supposed fix (is /dev/null allways present in hurd?)

change 

 close(1);
 dup(fds[0]);

to
 close(1);
 open("/dev/null", O_RDWR);



pipetest.c:
Run it on linux and hurd and see the difference.


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>

int main () {
    pid_t pid;
    int fds[2];
    int ret;

    printf("This program tests fork and pipe!\n");

    ret=pipe(fds);
    if(ret==-1){
        fprintf(stderr, "Pipe creation failed\n");
        exit(1);
    }


    if ((pid = fork()) < 0) {
        printf("Error fork not possible\n");
        exit(1);
    }
    else if (pid == 0) { // child
        close(fds[1]); //close write end
        close(0);
        dup(fds[0]);
        close(1);
        dup(fds[0]); 
        sleep(2); 
        fprintf(stderr, "Child is active\n");
        printf("Some text to stdout which is the dupped read end of the pipe\n")
;
        fprintf(stderr, "Child is still active\n");
        exit(0); 
    }
    // Parent
    while (1) {
        close(fds[0]); //close read end
        // here some write occurs in update-menu, is not important
        close(fds[1]); //close write end
        printf("Parent\n");
        sleep(1);
    }
    exit(0);
}



Reply to: