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]

1.7.8: write fails with EAGAIN


Hi,

recently, I found that cygwin-git was not able to 'cat-file' files that exceeded some size (in my case about 80MB).
I tracked this down to the cygwin implementation of write() that behaves quite odd in some cases.


I wrote a small program (source attached) that mmaps a given file and tries to write it to another file or stdout.

The results vary:

If the destination is a file (`writetest infile outfile` or `writetest infile > outfile`), the write succeeds in a single call.

If the destination is a pipe (`writetest infile | cat > outfile`), the write succeeds in most cases. BUT:

Under WinXP (XP Service Pack 2, 32bit), the call returns -1 and errno=EAGAIN. Nevertheless, SOME data is written to the pipe (in my case 4096 byte for each call).
This breaks git since it does an infinite loop while errno=EAGAIN.


It happens only for big files. On one machine, 87MB failed, on another one all went well up to ~200MB. It's not a disk space issue. It shouldn't be a memory issue - the test machine has 4GB.
I wasn't able to reproduce this on Win2k (32bit) nor Win7 (64bit) but maybe I didn't try enough file sizes...


cygwin version is cygwin-1_7_8-release, actually a fresh install made today.

Any ideas where to investigate further? EAGAIN is set for example in fhandler.cc, fhandler_base_overlapped::has_ongoing_io but I don't know whether that function is involved in my case.

Please Cc me, I'm not subscribed.

-Robert
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char** argv)
	{
	if (argc < 2)
		{
		fprintf(stderr, "wrong usage\n");
		return (1);
		}
	
	int fd;
	if ((fd = open(argv[1], O_RDONLY)) < 0)
		{
		perror("open");
		return (1);
		}
	
	struct stat st;
	if (fstat(fd, &st) < 0)
		{
		perror("fstat");
		close(fd);
		return (1);
		}
	size_t len = st.st_size;
	
	void* buf;
	if ((buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
		{
		perror("mmap");
		close(fd);
		return (1);
		}
	
	int fd2;
	if (argc > 2)
		{
		if ((fd2 = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, 0644)) < 0)
			{
			perror("open");
			munmap(buf, len);
			close(fd);
			return (1);
			}
		}
	else
		fd2 = 1;
	
	void* writebuf = buf;
	size_t to_write = len;
	
	while (to_write)
		{
		fprintf(stderr, "writing %u bytes...\n", to_write);
		ssize_t written = write(fd2, writebuf, to_write);
		int err = errno;
		fprintf(stderr, "result is %i, errno is %i\n", written, err);
		if (written > 0)
			{
			to_write -= written;
			writebuf += written;
			}
		}
	
	close(fd2);
	munmap(buf, len);
	close(fd);
	return (0);
	}

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