forkpty/select timeout issue
forkpty/select timeout issue
- Subject: forkpty/select timeout issue
- From: Kevin Wojniak <email@hidden>
- Date: Thu, 11 Dec 2014 17:53:36 -0800
I have some small code that calls forkpty, then in the child writes to stdout, and in the parent waits with select() for data to be available and then reads it all.
When testing on a 10.8 virtual machine and running the code repeatedly, I can get the select() to timeout about every other time I run the shell script. Also, sometimes the data is not read in the parent at all, read() just returns 0.
Here is the code:
===================
#include <stdio.h>
#include <util.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <assert.h>
int main()
{
int fd;
pid_t pid = forkpty(&fd, NULL, NULL, NULL);
if (pid == -1) {
printf("forkpty failed: %s\n", strerror(errno));
return -1;
} else if (pid == 0) {
if (write(STDOUT_FILENO, "hello", 5) != 5) {
_Exit(1);
}
_Exit(0);
}
// parent
int flags = fcntl(fd, F_GETFL, 0);
assert(flags != -1);
assert(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
char output[1024];
bzero(output, sizeof(output));
for (;;) {
// Wait for data to become available
fd_set readfd;
FD_ZERO(&readfd);
FD_SET(fd, &readfd);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
printf("select...\n");
int sel = select(fd+1, &readfd, NULL, NULL, &tv);
if (sel == -1) {
if (errno == EINTR) {
printf("select EINTR\n");
continue;
}
printf("select failed: %s\n", strerror(errno));
return 1;
} else if (sel == 0) {
printf("select timed out\n");
return 1;
}
// good
assert(FD_ISSET(fd, &readfd));
char foo[1024];
bzero(foo, sizeof(foo));
ssize_t num;
for (;;) {
num = read(fd, foo, sizeof(foo)-1);
if (num == -1 && errno == EINTR) {
printf("read EINTR\n");
continue;
}
break;
}
printf("read: %d\n", (int)num);
assert(num <= 5);
if (num == -1) {
printf("read failed: %s\n", strerror(errno));
return 1;
}
if (num == 0) {
// done
break;
}
foo[num] = 0;
strcat(output, foo);
}
printf("output: ->%s<-\n", output);
assert(strcmp(output, "hello") == 0);
int status;
assert(waitpid(pid, &status, 0) > 0);
assert(close(fd) == 0);
assert(WIFEXITED(status) == 1);
assert(WEXITSTATUS(status) == 0);
return 0;
}
===================
Compile: cc test.c -o test
Here is the shell script to run repeatedly:
===================
set -e
for i in `seq 200`; do
echo $i
./test
done
===================
This was stripped down from a larger code base to try and figure out what’s going on, but I don’t understand why it occasionally times out. I also reproduced on a 10.9 VM. I have reproduced the timeout on my native 10.10 system, but it is more rare (possibly due to being faster and more cores?).
Is there something I’m missing? I’ve been studying a lot of example code and cannot find anything that I should be doing extra.
Any help would be appreciated!
Kevin
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden