[php] fread nach select blockiert
-
Hey, ich versuch ein Video on the fly zu codieren und die Eingabe und Ausgabe durch php zu leiten und dann über Netzwerk zu verschicken.
Damit das Script nirgends hängenbleibt frage ich mit stream_select die Streams ab, die ohne zu blocken gelesen und/oder geschrieben werden können.$mencoder[ 'input' ] ist stdin von ffmpeg, mencoder[ 'output' ] ist stdout, beide über proc_open bekommen... client ist ein socket, das mit stream_socket_accept akzeptiert wurde...
$input = fopen( "/data1/bla/film.avi", "rb" ), $buffer_input = array(); $buffer_output = array(); $run = true; $error = 0; while( $input && $run && $error < 3 ) { $read = array(); #adding read fd if we need data if( sizeof( $buffer_input ) < 1024 ) $read[] = $input; if( sizeof( $buffer_output ) < 1024 ) $read[] = $mencoder[ 'output' ]; # adding write fd if we have data $write = array(); if( sizeof( $buffer_output ) ) $write[] = $client; if( sizeof( $buffer_input ) ) $write[] = $mencoder[ 'input' ]; #select $rc = stream_select( $read, $write, $ex = NULL, 5, 0 ); if( $rc === false ) { echo "error doing select\n"; break; } if( $rc === 0 ) { echo "no data in 5 seconds, try again"; $error++; continue; } $error = 0; foreach( array_merge( $read, $write ) as $socket ) { if( $socket == $input ) { echo "read input from source...\n"; $buffer_input[] = fread( $input, 4096 ); } if( $socket == $mencoder[ 'output' ] ) { echo "read data from encoder...\n"; $block = fread( $mencoder[ 'output' ], 4096 ); $buffer_output[] = fread( $mencoder[ 'output' ], 4096 ); } if( $socket == $client ) { echo "write data to the client\n"; fwrite( $client, array_shift( $buffer_output ) ); } if( $socket == $mencoder[ 'input' ] ) { echo "write data to encoder...\n"; fwrite( $mencoder[ 'input' ], array_shift( $buffer_input ) ); } } }das problem ist jetzt jedoch folgendes: er blockiert trotzdem!
nach einigen sekunden umwandeln kommt:... read input from source... write data to encoder... read input from source... read data from encoder... write data to encoder... read input from source... read data from encoder...das heißt, erhängt beim fread vom $mencoder[ 'output' ]... das düfte er jedoch nicht, da durch das stream_select sichergestellt sein sollte, dass er ohne zu blockieren lesen kann... (das passiert übrigens nach etwa 800kb)
Das script läuft unter Linux und mit php5.2.0-8+etch4 aus der konsole
Hat vielleicht irgendwer eine Ahnung, woran das liegen könnte?Gruß, Olli
-
kleiner fehler, statt
$block = fread( $mencoder[ 'output' ], 4096 ); $buffer_output[] = fread( $mencoder[ 'output' ], 4096 );natrlich nur die zweite zeile. aber das ändert leider nichts daran...
-
Ich habe das ganze nochmal 1:1 nach Python portiert, in der Hoffnung, dass der Fehler in PHP zu finden ist... doch Pustekuchen, er blockiert einfach, obwohl er das nicht dürfte!
-
musst ja noch in den non-blocking modus schalten, ich glaube mit ioctl
-
Nein nein, erstmal ist das php, da gibts kein ioctl, und zweitens ist es durch das select ja prinzipiell ausgeschlossen, dass ein read/write blocken kann.
Nichts destotrotz habe ich das bereits mal in den non-blocking Modus gestellt, dann kehrt der Aufruf erwartungsgemäß sofort zurück, jedoch gibt fread/fwrite dann 0 zurück und tut nichts...
Das Problem ist ja, dass sowas nicht vorkommen "kann"...
-
und zweitens ist es durch das select ja prinzipiell ausgeschlossen, dass ein read/write blocken kann.
quatsch
-
select() and pselect() allow a program to monitor multiple file
descriptors, waiting until one or more of the file descriptors become
"ready" for some class of I/O operation (e.g., input possible). A file
descriptor is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
-
wenn das select durchgeht heisst das dass du sicher 1 byte lesen kannst. niemand garantiert dir dass du 4096 bytes lesen kannst.
-
Soweit ich weiß heißt dass dann aber nicht, dass er blockiert, sobald er mehr anfordert als er lesen kann:
It is not an
error if this number is smaller than the number of bytes requested;
this may happen for example because fewer bytes are actually available
right now (maybe because we were close to end-of-file, or because we
are reading from a pipe, or from a terminal), or because read() was
interrupted by a signal.Dann ließt er halt nur das eine von den 4096 bytes und gibt 1 zurück...