How to detect stream_copy_to_stream errors?

I have some code that is simplified, looks something like this:

  $ fout = fsockopen ($ host, 80);
 stream_set_timeout ($ fout, 10 * 3600);  // 10 hours
 $ fin = fopen ($ file, 'rb');  // not really a file stream, but good enough proxy here
 $ readbytes = stream_copy_to_stream ($ fin, $ fout);
 if (! $ readbytes) die ('copy failed');

However, sometimes I get the following type of error:

  Notice: stream_copy_to_stream (): send of 952 bytes failed with errno = 104 Connection reset by peer in ...
 Notice: stream_copy_to_stream (): send of 952 bytes failed with errno = 32 Broken pipe in ...

And checking for $ readbytes there will not result in an error. I know that you can check the total file length with the number of bytes copied, but this only works if the total stream length can be determined in advance.

As this happens randomly, I assume the connection is simply dropped for some strange reason (but if anyone has any suggestions to reduce the likelihood of this, I’m all ears). But it would be nice to know if the transfer was completely or not. Is there a way to detect the problem without:

  • to know the flow length in advance
  • connect to the PHP error handler to get an error

... or perhaps using the fread / fwrite buffer loop, checking the length of the written bytes, is the best solution here?

Thanks.

+4
source share
1 answer

So here is my stream copy function that tries to detect errors, but it still seems to not work (and I thought that fwrite should have returned the correct number of bytes)

  function stream_copy ($ in, $ out, $ limit = null, $ offset = null) {
     $ bufsize = 32 * 1024;
     if (isset ($ offset)) fseek ($ in, $ offset, SEEK_CUR);
     while (! feof ($ in)) {
         if (isset ($ limit)) {
             if (! $ limit) break;
             $ data = fread ($ in, min ($ limit, $ bufsize));
         } else
             $ data = fread ($ in, $ bufsize);
         $ datalen = strlen ($ data);
         $ written = fwrite ($ out, $ data);
         if ($ written! = $ datalen) {
             return false;  // write failed
         }
         if (isset ($ limit)) $ limit - = $ datalen;
     }
     return true;
 } 

In the above function, I still get "true" even if an error is displayed.

So, I will just try to connect to the PHP error handler. Did not test the following, but I assume that it should work

  function stream_copy_to_stream_testerr ($ source, $ dest) {
     $ args = func_get_args ();

     global $ __ stream_copy_to_stream_fine;
     $ __ stream_copy_to_stream_fine = true;

     set_error_handler ('__ stream_copy_to_stream_testerr');
     call_user_func_array ('stream_copy_to_stream', $ args);
     restore_error_handler ();

     return $ __ stream_copy_to_stream_fine;
 }
 function __stream_copy_to_stream_testerr () {
     $ GLOBALS ['__ stream_copy_to_stream_fine'] = false;
     return true;
 } 

Awful, but the only solution I see.

+3
source

Source: https://habr.com/ru/post/1344713/


All Articles