[GRASS-dev] native WinGRASS and attribute data deadlock, next try

Moritz Lennert mlennert at club.worldonline.be
Thu Oct 4 12:38:23 EDT 2007


On 24/09/07 03:41, Glynn Clements wrote:
> Moritz Lennert wrote:
> 
>>> My next suggestion is to re-write xdr_stdio to use read() and write()
>>> instead of fread() and fwrite(), e.g.:
>>>
>>> -	if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
>>> +	if (read(fileno((FILE *)xdrs->x_private), (caddr_t)lp, sizeof(long)) !=
>>> sizeof(long))
>> That seems to work !
> 
> Now that's strange. I was expecting it to provide more information on
> the errors, not to work.
> 
> On Unix, read/write can return short counts on pipes. If a process
> tries to write 4 bytes to a pipe, and there's only enough space for 2
> bytes, write() will return 2 rather than waiting for the pipe to
> drain. Similarly if you try to read more data than is available in the
> pipe.
> 
> If you want to block until the requested amount of data has been read
> or written, you need to either use readn/writen (which are
> non-standard), or implement them yourself, e.g.:
> 
> ssize_t readn(int fd, void *buf, size_t count)
> {
> 	ssize_t total = 0;
> 
> 	while (total < count)
> 	{
> 		ssize_t n = read(fd, (char *) buf + total, count - total)
> 		if (n < 0)
> 			return n;
> 		if (n == 0)
> 			break;
> 		total += n;
> 	}
> 
> 	return total;
> }
> 
> ssize_t writen(int fd, const void *buf, size_t count)
> {
> 	ssize_t total = 0;
> 
> 	while (total < count)
> 	{
> 		ssize_t n = write(fd, (const char *) buf + total, count - total)
> 		if (n < 0)
> 			return n;
> 		if (n == 0)
> 			break;
> 		total += n;
> 	}
> 
> 	return total;
> }
> 
> The above assumes that non-blocking I/O hasn't been enabled for the
> descriptor. If it has, you need to either disable it for the duration
> of the function or use select() or poll() to wait until the descriptor
> is ready.
> 
>> I'll post new binaries as soon as compilation is over, so that others can
>> test as well.
> 
> If you want to test it, I'd suggest reducing the size of the pipes in
> lib/db/dbmi_client/start.c. A larger pipe won't prevent errors, but it
> may make them less likely to show up.
> 

I changes the values in lines 146 & 147 and went down all the way to 2 ( 
from the current setting of 250000): I cannot reproduce the 
deadlock...v.out.ogr works as it should.

So, where should we go from here ? Is it still wiser to implement 
readn/writen as you suggest above ? If yes, where and how do I see if 
non-blocking I/O is enabled or not (on MSDN it says: "In multithreaded 
programs, no locking is performed. The file descriptors returned are 
newly opened and should not be referenced by any thread until after the 
_pipe call is complete." - Is this what you mean ?) ?

Benjamin, could you try the simple write/read (instead of fwrite/fread) 
solution, so that we can make sure that this works for someone else ?

Moritz




More information about the grass-dev mailing list