mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* splice lost data
@ 2009-04-07 19:48 xinglp
  2009-04-08  7:20 ` Vegard Nossum
  0 siblings, 1 reply; 3+ messages in thread
From: xinglp @ 2009-04-07 19:48 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 86 bytes --]

2.6.29.1 in VM

When recv data more than 8K (1024*8) bytes at once, data lost happen.

[-- Attachment #2: splice_test.c --]
[-- Type: text/plain, Size: 1267 bytes --]

#define SPLICE_SIZE	(1024*8)//when define SPLICE_SIZE bigger than (1024*8) data lost happen.
//This function is called when EPOLLIN on Socket
void RecvBySplice(int hFile,int Socket)
{
	ssize_t	SizeToRead;
	ssize_t	SizeRead;
	ssize_t	SizeLeft;
	ssize_t	SizeWrite;

	while(ContentLength>0)//ContentLength is global
	{
		SizeToRead	=SPLICE_SIZE>ContentLength?ContentLength:SPLICE_SIZE;

		SizeRead	=splice(Socket,NULL,Pipes[1],NULL,SizeToRead,SPLICE_F_NONBLOCK);//Pipes[] is global

		if(SizeRead>0)
		{
			ContentLength-=SizeRead;

			SizeLeft=SizeRead;
			
			while(SizeLeft>0)
			{
				SizeWrite=splice(Pipes[0],NULL,hFile,NULL,SizeLeft,SPLICE_F_NONBLOCK);//Pipes[] is global

				if(SizeWrite>0)
				{
					SizeLeft-=SizeWrite;
				}
				else if(EINTR==errno)
				{
					continue;
				}
				else
				{
					perror("splice");
					return;
				}
			}

			if(SizeRead<SizeToRead)
			{
				return;//No more data in socket buf
			}
		}
		else
		{
			if(0==SizeRead)
			{
				perror("peer close");
				return;
			}
			else
			{
				if(EAGAIN==errno)
				{
					return;
				}
				else if(EINTR==errno)
				{
					continue;
				}
				else
				{
					perror("splice");
					return;
				}
			}
		}
	}
}


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: splice lost data
  2009-04-07 19:48 splice lost data xinglp
@ 2009-04-08  7:20 ` Vegard Nossum
  2009-04-08  7:54   ` xinglp
  0 siblings, 1 reply; 3+ messages in thread
From: Vegard Nossum @ 2009-04-08  7:20 UTC (permalink / raw)
  To: xinglp; +Cc: linux-kernel

2009/4/7 xinglp <xinglp@gmail.com>:
> 2.6.29.1 in VM
>
> When recv data more than 8K (1024*8) bytes at once, data lost happen.
>

Don't know if this is related to the problem you report, but your code is buggy.

You're checking errno before you know that splice() returned -1. Now,
I don't know the actual implementation, but as with most system calls,
the interface specifies only that errno is updated when the function
returns -1:

       "On error, splice() returns -1 and errno is set to indicate the
error." (man 2 splice)

You're also not checking explicitly for the return value 0, which
would possibly also not set errno (i.e. you're using perror() in the
case where splice() returned 0).

Please let me know if this fixes your problem!


Vegard

-- 
"The animistic metaphor of the bug that maliciously sneaked in while
the programmer was not looking is intellectually dishonest as it
disguises that the error is the programmer's own creation."
	-- E. W. Dijkstra, EWD1036

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: splice lost data
  2009-04-08  7:20 ` Vegard Nossum
@ 2009-04-08  7:54   ` xinglp
  0 siblings, 0 replies; 3+ messages in thread
From: xinglp @ 2009-04-08  7:54 UTC (permalink / raw)
  To: Vegard Nossum; +Cc: linux-kernel

2009/4/8, Vegard Nossum <vegard.nossum@gmail.com>:
> 2009/4/7 xinglp <xinglp@gmail.com>:
>
> Don't know if this is related to the problem you report, but your code is buggy.
>
> You're checking errno before you know that splice() returned -1. Now,
> I don't know the actual implementation, but as with most system calls,
> the interface specifies only that errno is updated when the function
> returns -1:
>
>       "On error, splice() returns -1 and errno is set to indicate the
> error." (man 2 splice)
>
> You're also not checking explicitly for the return value 0, which
> would possibly also not set errno (i.e. you're using perror() in the
> case where splice() returned 0).
>
> Please let me know if this fixes your problem!
>
>
> Vegard
>

I see ,but that's not the point.
Now I knew the reason while data lost:

I use epoll(ET) and splice() to recv  data  and write it to DISK (
through pipe).
 And in the earlier time I use epoll(ET) and recv() to recv data  and
write it to DISK (through buffer).

But recv() and splice() is not the same when they were used with epoll(ET).

By 'man epoll' I got a QA.

Q9    Do  I need to continuously read/write a file descriptor until
EAGAIN when using
      the EPOLLET flag (edge-triggered behavior) ?

A9    No you don't.  Receiving an event from epoll_wait(2) should
suggest to you that
      such file descriptor is ready for the requested I/O operation.
You have simply
      to consider it ready until you will receive the next EAGAIN.
When and how  you
      will  use such file descriptor is entirely up to you.  Also, the
condition that
      the read/write I/O space is exhausted can be detected by
checking the amount of
      data  read  from  / written to the target file descriptor.  For
example, if you
      call read(2) by asking to read a certain amount of data and
read(2)  returns  a
      lower  number  of bytes, you can be sure of having exhausted the
read I/O space
      for such file descriptor.  The same is true when writing using
the write(2).

So I break the loop at "returns a lower number  of bytes" when I use
recv(), that works well.

But If I do the same "break" with splice(). epoll_wait won't return
new EPOLLIN until new data come in. So maybe lost few data at the
tail(in fact just lost events).

As <w@1wt.**>  said:
"splice() does not always forward all available data".

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-04-08  7:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-07 19:48 splice lost data xinglp
2009-04-08  7:20 ` Vegard Nossum
2009-04-08  7:54   ` xinglp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®