I see a problem immediately with this program: you forgot to close the unused
ends of the pipe after forking. That could explain why it hangs after you
thinkg you've closed the writing end. The reader process has an unused copy
of the writing end of the pipe, so the reading end will block on
select-for-read because there is still the possibility of writes happening.
I cleaned up your program and it behaves as expected for me, but I'm not on
kernel 2.2.2 yet.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#define READ_SIZE 15
static char buffer[READ_SIZE];
int pipe_fd[2];
#define p_write pipe_fd[1]
#define p_read pipe_fd[0]
static int client(void)
{
int sock, flgs, len, cnt;
fd_set rfds;
sock=p_read;
close(p_write);
flgs = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flgs|O_NONBLOCK);
cnt = 0;
do
{
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
if(select(sock + 1, &rfds, NULL, NULL, NULL) <= 0)
{ perror("select()"); exit(1); }
len = read(sock, buffer, READ_SIZE);
if(len > 0)
cnt += len;
printf("cnt=%d\n",cnt);
} while(len>0);
close(sock);
printf("Got %d bytes.\nConnection closed\n", cnt);
return 0;
}
#define WRITE_SIZE 1585
static const char str[WRITE_SIZE];
static void sigint(int s)
{
(void)s;
printf("***SIGINT\n");
fflush(stdout);
close(p_write);
close(p_read);
exit(0);
}
static void sigpipe(int s)
{
(void)s;
printf("***SIGPIPE\n");
fflush(stdout);
close(p_write);
close(p_read);
exit(0);
}
static int serv(void)
{
int sock;
int i, size, written, flgs;
const char *ptr;
fd_set wfds;
sock=p_write;
close(p_read);
flgs = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flgs|O_NONBLOCK);
printf("sending %d bytes of data...\n",3200*sizeof(str));
for(i = 0; i < 3200; i++)
{
size = sizeof(str);
ptr = str;
while(size)
{
FD_ZERO(&wfds);
FD_SET(sock, &wfds);
if(select(sock+1, NULL, &wfds, NULL, NULL) < 0)
{ perror("select()"); abort(); }
if((written = write(sock, ptr, size)) < 0)
{ perror("write()"); abort(); }
size -= written;
ptr += written;
}
}
printf("ready, sent %d bytes of data\n",3200*sizeof(str));
fflush(stdout);
close(sock);
exit(0);
}
int main(void) {
int pid;
pipe(pipe_fd);
signal(SIGINT, sigint);
signal(SIGPIPE, sigpipe);
pid=fork();
if (pid<0) {
perror("Main:");
exit(1);
}
if (pid==0) {
serv();
} else {
client();
}
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/