PTY dies when master in parent process is closed.
Takashi Yano
takashi.yano@nifty.ne.jp
Thu Mar 5 12:59:00 GMT 2015
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.yano@nifty.ne.jp>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cygcheck.out
Type: application/octet-stream
Size: 100144 bytes
Desc: not available
URL: <http://cygwin.com/pipermail/cygwin/attachments/20150305/20c14ec9/attachment.obj>
-------------- next part --------------
--
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
More information about the Cygwin
mailing list