Zaseknuté čtení z proc_open rubrika: Programování: PHP
Ahoj. Mohl by mi prosím někdo vysvětlit následující chování?
Mám takovýto script:
A teď se pokouším tento script obsluhovat. Otevřu si process:
tak, a teď mám takovýto problém:
První problém je, že když načtu velkej blok najednout, tak je to v pořádku:
echo fread($pipes[1], 1024);
Když ale budu číst malé bloky, tak pokud čtu více, než kolik zbejvá, tak se to kousne:
Chápu to tak, že u prvního volání může být velikost větší než požadovaná, ale u druhého si musím nejdřív zjistit, jestli nějaké zbývají pomocí:
stream_get_meta_data($pipes[1])['unread_bytes'];
echo fread($pipes[2], 1024);
Nekousne se, říká se tomu blokující volání. Když voláš fread()
a v bufferu není ani bajt (ani EOF), tak on čeká, až se tam aspoň jeden bajt objeví, do té doby "blokuje" (čeká ve fread()
). Podívej se na stream_select()
- ten ti otestuje, ze kterých streamů můžeš aktuálně číst bez blokování (t.j. ve kterých streamech na tebe čeká aspoň jeden bajt), resp. zablokuje se, dokud aspoň v jednom ze streamů něco nepřijde.
V podstatě chceš asi něco jako (neotestováno):
<?php $process = proc_open('./readwrite.php', [ 0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'), ], $pipes, __DIR__); $to_be_written = "aaa\n"; for (;;) { $sr = array($pipes[1], $pipes[2]); $sw = array(); $se = array($pipes[0], $pipes[1], $pipes[2]); if (strlen($to_be_written) !== 0) $sw[] = $pipes[0]; // cekej max. 1 vterinu na jakoukoli aktivitu ve streamech $changed = stream_select($sr, $sw, $se, 1); if ($changed === FALSE) die("nejaka chyba v stream_select()\n"); // zadna aktivita na streamech, jen uplynul timeout if ($changed === 0) { echo "tick...\n"; continue; } // koukni, na kterych streamech byla jaka aktivita a zpracuj ji if (in_array($pipes[1], $sr)) printf("stdout: %s\n", fread($pipes[1], 1024)); if (in_array($pipes[2], $sr)) printf("stderr: %s\n", fread($pipes[2], 1024)); if (in_array($pipes[0], $sw)) { $written = fwrite($pipes[0], $to_be_written, 1024); if ($written === FALSE) die("nejaka chyba v fwrite()\n"); $to_be_written = substr($to_be_written, $written); } if (in_array($pipes[0], $se)) die("chyba na stdin\n"); if (in_array($pipes[1], $se)) die("chyba na stdout\n"); if (in_array($pipes[2], $se)) die("chyba na stderr\n"); }
Pro zobrazení všech 2 odpovědí se prosím přihlaste:
Nebo se přihlaste jménem a heslem:
Komentáře