[MPlayer-dev-eng] [patch 3/5] Fix stream_write_buffer to make sure all requested bytes are written

Tobias Diedrich ranma at tdiedrich.de
Tue Jan 11 00:38:21 CET 2011


Reimar Döffinger wrote:
> On 6 jan 2011, at 19:30, Tobias Diedrich <ranma at tdiedrich.de> wrote:
> > Reimar Döffinger wrote:
> >> On Thu, Jan 06, 2011 at 05:06:33PM +0100, Tobias Diedrich wrote:
> >>> Index: mplayer-patchset1/stream/stream_file.c
> >>> ===================================================================
> >>> --- mplayer-patchset1.orig/stream/stream_file.c    2011-01-06 16:18:13.945756000 +0100
> >>> +++ mplayer-patchset1/stream/stream_file.c    2011-01-06 16:45:35.911193000 +0100
> >>> @@ -52,13 +52,32 @@
> >>> };
> >>> 
> >>> static int fill_buffer(stream_t *s, char* buffer, int max_len){
> >>> -  int r = read(s->fd,buffer,max_len);
> >>> -  return (r <= 0) ? -1 : r;
> >>> +  int nr = 0;
> >>> +  int r;
> >>> +  while (nr < max_len) {
> >>> +    r = read(s->fd,buffer,max_len);
> >>> +    if (r < 0)
> >>> +      return -1;
> >>> +    max_len -= r;
> >>> +    buffer += r;
> >>> +    nr += r;
> >>> +    if (r == 0)
> >>> +      break;
> >>> +  }
> >>> +  return nr;
> >>> }
> >> 
> >> Have you seen cases where this is necessary for read? The reason I
> >> dislike it is because I think it might interfere with the code that
> >> tries to do a clean exit on CTRL+C.
> >> Also it looks to me like your code allows a 0 return value (which
> >> previously was not possible), IIRC that can cause hangs.
> > 
> > Well, given that I was adding retry code for write I thought I
> > should look at the read codepath too.
> > Posix spec says that read() too may be interrupted by signals and
> > then return less than requested (probably won't happen on Linux since
> > reads should be blocking)
> 
> All signals are fatal for MPlayer, however there's a risk your patch makes it more likely to get stuck in a loop so it can't shutdown cleanly.
> 
> > and of course it can happen on pipes/fifos.
> 
> Why? For writes there are good reasons, but I see no reason why reads from pipes or fifos should ever return only partial data (that kind of info seems rather hard to find though).

Maybe a bit of a contrieved example, but:

(echo foo; sleep 1; echo bar) > test.fifo
If I start a read() on the fifo before executing this, the first read
returns "foo" and I have to call read a second time to get the
second half.  So if we want stream_file to work reliably on
pipes/fifos this would be needed I think.

Using the following test program I get:
|ranma at navi:~$ ./fifotest
|nr=3
|nr=3


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
	int pid;
	int pfd[2];
	int nr;
	char buf[4096];

	if (pipe(pfd) == -1) {
		perror("pipe");
		return EXIT_FAILURE;
	}

	pid = fork();
	if (pid == -1) {
		perror("fork");
		return EXIT_FAILURE;
	}

	if (pid == 0) {
		close(pfd[0]);
		write(pfd[1], "foo", 3);
		sleep(1);
		write(pfd[1], "bar", 3);
		close(pfd[1]);
	} else {
		close(pfd[1]);
		nr = read(pfd[0], buf, sizeof(buf));
		printf("nr=%d\n", nr);
		nr = read(pfd[0], buf, sizeof(buf));
		printf("nr=%d\n", nr);
		close(pfd[0]);
	}

	return EXIT_SUCCESS;
}

-- 
Tobias						PGP: http://8ef7ddba.uguu.de


More information about the MPlayer-dev-eng mailing list