Package: cygwin
Version: 1.7.35-1

PTY of cygwin dies when master fd in parent process
is closed while a child process keeps valid master fd.

To reproduce this problem:
1) Compile following C sources (Test Case 1, 2)
2) Execute them.

Expected results are both:
01234567890

However, result of Test Case 2 is:
Hungup
while Test Case 1 is as expected.

Difference between Test Case 1 and Test Case 2 is
which process is worked in parent. In other words,
master is in parent process in Test Case 1, while
master is in child process in Test Case 2.

I looked into cygwin source code, and found the cause.
fhandler_pty_master::close() calls get_ttyp()->set_master_closed()
if it is called from the process which opend the master.
It is regardless whether other processes have the valid
master handle.

get_ttyp()->set_master_closed() should be called only
when the last valid master handle among all processes
is closed.

Additionally, I am not sure whether SIGHUP should be
generated when the master is closed.


/***************/
/* Test Case 1 */
/***************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <pty.h>
#include <wait.h>

int main()
{
    int master, slave;
    pid_t pid;

    if ( openpty(&master, &slave, NULL, NULL, NULL) < 0) {
        perror("openpty()");
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid < 0) {
        perror("fork()");
        exit(EXIT_FAILURE);
    }

    if (pid != 0) { /* Parent */
        close(slave);
        write(master, "0123456789\n", 11);
        usleep(100000); /* wait until slave read() */
        close(master);
        wait(NULL);
    } else { /* Child */
        char buf[BUFSIZ];
        int len;
        close(master);
        len = read(slave, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
        close(slave);
    }

    return EXIT_SUCCESS;
}


/***************/
/* Test Case 2 */
/***************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <pty.h>
#include <wait.h>

int main()
{
    int master, slave;
    pid_t pid;

    if ( openpty(&master, &slave, NULL, NULL, NULL) < 0) {
        perror("openpty()");
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid < 0) {
        perror("fork()");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) { /* Child */
        close(slave);
        write(master, "0123456789\n", 11);
        usleep(100000); /* wait until slave read() */
        close(master);
    } else { /* Parent */
        char buf[BUFSIZ];
        int len;
        close(master);
        len = read(slave, buf, sizeof(buf));
        write(STDOUT_FILENO, buf, len);
        close(slave);
        wait(NULL);
    }

    return EXIT_SUCCESS;
}


-- 
Takashi Yano <takashi.y...@nifty.ne.jp>

Attachment: cygcheck.out
Description: Binary data

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to