This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fifo blocking and performance issues - some more code snips


Forgot to mention in my last code snip post that the Linux code below is the 
"desired" behavior of the fifos to match the existing Linux code in the SIMPL 
toolkit.    

In this Linux code snip we open the receive end of the fifo as RDWR (without 
the O_NONBLOCK flag)  and Linux conveniently allows that open to occur even if 
the other end of the fifo isn't yet there.   In Cygwin this open blocks, hence 
the need for the O_NONBLOCK flag.   Furthermore the Linux code conveniently 
blocks on the read() call.   In Cygwin this read doesn't block (probably 
because it has been open O_NONBLOCK to overcome the open blocking issue) 
hence the need for the select() hack.

I haven't had time to replicate the blocking WRONLY fifo open problem that I 
noticed in my SIMPL toolkit testing on Cygwin.    Early indications is that 
this open blocks if at least one other process has opened the fifo WRONLY and 
remains alive.    Once again the behavior on Linux is that this open doesn't 
block regardless of how many other processes have the fifo open WRONLY.

Thanks again for all your help.

bob
PS.
The astute reader might be asking why RDWR and not RDONLY.   Turns out that 
RDWR fifos on Linux allow for some detection of vanished partners which helps 
with cleanup in such scenerios.    The behavior on Cygwin is the same with 
RDONLY and RDWR fifos in that the open blocks until the other partner opens the 
fifo.

PS2.
The other astute reader will recognize the QNX style Send-Receive-Reply 
message pass in these code snips.   The receiver opens a fifo RDWR and blocks 
on a read() waiting for an integer value.   The sender opens the receiver's 
fifo WRONLY and submits an integer and then blocks on its own RDWR fifo waiting 
for a response.   Meanwhile the receiver read() unblocks and reads out an 
integer.  The receiver then  submits the response integer to a WRONLY end of 
the sender's reply fifo.  ie. a synchronous message pass.   In the SIMPL 
toolkit this integer exchange on the fifos is used to synchronize a shared 
memory exchange of the actual message bytes.

========= begin sender2.c ===============

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/timeb.h>

int blocked_read(int, char *, int);

int main(int argc, char *argv[])
{
char command[80];
char fifoname[80];
int fd=-1;
int rfd;
int i;
int j;
int *r;
int bytesToGo;
int numBytes;
char buf[5];
char *p;
int rc;
struct timeb before;
struct timeb after;
int msec;

printf("fifo sender starting\n");

sprintf(fifoname,"/tmp/fsender");

mkfifo(fifoname, 0666);
chmod(fifoname, 0666);

printf("starting receiver2\n");

sprintf(command,"./receiver2&");
rc=system(command); 

printf("receiver2 started\n");

sleep(2);

fd=open(fifoname, O_RDWR);
//fd=open(fifoname, O_RDWR|O_NONBLOCK);
rfd=open("/tmp/freceiver", O_WRONLY);

ftime(&before);

for(j=1; j<100; j++)
	{
printf("j=%d\n",j);

	write(rfd,&j,sizeof(int));

	numBytes=0;
	memset(buf,0,4);
	p=buf;
	for(i=0; i< 10; i++)
		{
		bytesToGo=sizeof(int) - numBytes;

printf("bytesToGo=%d numBytes=%d\n",bytesToGo,numBytes);

		if(bytesToGo <= 0) break;

		rc=blocked_read(fd,p,bytesToGo);
printf("sender rc[%d]=%d\n",i,rc);
		if(rc == 0)
			{
			printf("got eof\n");
			}
		else
		if(rc == -1)
			{
			printf("%s\n",strerror(errno));
			}
		else
			{
			numBytes+=rc;
			p+=rc;
			}
		} //end for i

printf("buf: 0x%X-%X-%X-%X\n",buf[0],buf[1],buf[2],buf[3]);
	r=(int *)buf;

printf("reply[%d]=%d\n",j,*r);
	} // end for j

ftime(&after);
msec=(after.time - before.time)*1000 + (after.millitm - before.millitm);
printf("%d messages took %d ms\n",j, msec);

sleep(1);

unlink(fifoname);
unlink("/tmp/freceiver");
	
exit(0);
} // end sender


int blocked_read(int fd, char *buff, int size)
{
int rc;
//fd_set inset;

//FD_ZERO(&inset);
//FD_SET(fd, &inset);

//printf("send: before select\n");
//select(fd+1, &inset, NULL, NULL, NULL);
printf("send: before read\n");
rc=read(fd,buff,size);

printf("send: read rc=%d\n",rc);
return(rc);
} // end blocked_read
========= end sender2.c ================

========== begin receiver2.c ===========

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>

int blocked_read(int, char *, int);

int main(int argc, char *argv[])
{
char command[80];
char fifoname[80];
int fd;
int rfd;
int dummy;
int i;
int j;
int k;
int *r;
int bytesToGo;
int numBytes;
char buf[4];
char *p;
int rc;

printf("fifo receiver starting\n");

sprintf(fifoname,"/tmp/freceiver");

mkfifo(fifoname, 0666);
chmod(fifoname, 0666);

fd=open(fifoname, O_RDWR);
//fd=open(fifoname, O_RDWR | O_NONBLOCK);

for(k=0; k<99; k++)
	{
	numBytes=0;
	p=buf;
	for(i=0; i< 10; i++)
		{
		bytesToGo=sizeof(int) - numBytes;

		if(bytesToGo <= 0) break;

//	rc=read(fd,p,bytesToGo);
		rc=blocked_read(fd,p,bytesToGo);
printf("recv rc[%d]=%d\n",i,rc);
		if(rc == 0)
			{
			printf("recv eof\n");
			}
		else
		if(rc == -1)
			{
			printf("%s\n",strerror(errno));
			}
		else
			{
			numBytes+=rc;
			p+=rc;
			}
		} // end for i

	r=(int *)buf;
	j=*r;
printf("received[%d]=%d\n",k,j);
	j++;

//	sleep(1);
	
	rfd=open("/tmp/fsender", O_WRONLY);
	write(rfd,&j,sizeof(int));
	close(rfd);
	} // end for k

unlink(fifoname);

exit(0);
} // end receiver

int blocked_read(int fd, char *buff, int size)
{
int rc;
//fd_set inset;

//FD_ZERO(&inset);
//FD_SET(fd, &inset);

//printf("recv: before select\n");
//select(fd+1, &inset, NULL, NULL, NULL);
printf("recv: before read\n");
rc=read(fd,buff,size);

printf("recv: read rc=%d\n",rc);

return(rc);
} // end blocked_read
========== end receiver2.c =============

========= begin linux.out2 =============

sender2
fifo sender starting
starting receiver2
receiver2 started
fifo receiver starting
recv: before read
j=1
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[0]=1
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x2-0-0-0
reply[1]=2
j=2
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[1]=2
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x3-0-0-0
reply[2]=3
j=3
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[2]=3
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x4-0-0-0
reply[3]=4
j=4
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[3]=4
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5-0-0-0
reply[4]=5
j=5
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[4]=5
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x6-0-0-0
reply[5]=6

...

j=92
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[91]=92
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5D-0-0-0
reply[92]=93
j=93
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[92]=93
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5E-0-0-0
reply[93]=94
j=94
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[93]=94
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5F-0-0-0
reply[94]=95
j=95
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[94]=95
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x60-0-0-0
reply[95]=96
j=96
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[95]=96
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x61-0-0-0
reply[96]=97
j=97
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[96]=97
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x62-0-0-0
reply[97]=98
j=98
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[97]=98
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x63-0-0-0
reply[98]=99
j=99
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[98]=99
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x64-0-0-0
reply[99]=100
100 messages took 8 ms
========= end linux.out2 ===============


--
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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]