curl_multi_exec (): предоставленный ресурс не является допустимым ресурсом дескриптора cURL в - PullRequest
0 голосов
/ 14 октября 2019

Недавно я обновился до PHP 7.2 (с 5.x), и один из моих плагинов Opencart начал вести себя странно. Я думаю, что это происходит, когда curl пытается подключиться к ссылке 404. В журнале я вижу:

curl_multi_exec(): supplied resource is not a valid cURL handle resource in

Я думаю, что он находится в бесконечном цикле, потому что он не останавливается сам по себе.

Код следующий:

public function uploadMultipleImages($images, $importer, &$parent)  {   
    set_error_handler('error_handler_for_export',E_ALL);
    register_shutdown_function('fatal_error_shutdown_handler_for_export');
    if(count($images) == 0)
        return true;
    //ini_set('memory_limit', '512M');
    ini_set('memory_limit', '-1');
    try {
        $img = array();
        $directory = rtrim(DIR_IMAGE . 'data/' . str_replace('../', '', $importer), '/');

        if(!is_dir($directory))
            if (!mkdir($directory, 0777, true)) 
                die('Failed to create folders...');

        $pack = 30;

        $chs = array();
        $cmh = curl_multi_init();

        if ($parent->config->get('config_error_log')) {
            $parent->log->write('PHP xml Image: Images to download: ' . count($images));
        }

        for ($t = 0; $t < $pack && $t < count($images) ; $t++)
        {

            $chs[$t] = curl_init();
            curl_setopt($chs[$t], CURLOPT_URL, $images[$t]['image']);
            curl_setopt($chs[$t], CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($chs[$t], CURLOPT_CONNECTTIMEOUT, 100);
            curl_setopt($chs[$t], CURLOPT_TIMEOUT, 100);
            curl_multi_add_handle($cmh, $chs[$t]);    
            if ($parent->config->get('config_error_log')) {
                $parent->log->write('PHP Importer Images: Added to queue image 51: ' . $images[$t]['image'] . ' CNT: '. count($chs));
            }
        }

        do {

            while(($execrun = curl_multi_exec($cmh, $running)) == CURLM_CALL_MULTI_PERFORM);
            if($execrun != CURLM_OK)
                break;
            //usleep(200000); 
            // Block for data in / output; error handling is done by curl_multi_exec
            curl_multi_select($cmh);

            // a request was just completed -- find out which one
            while($done = curl_multi_info_read($cmh)) {

                $info = curl_getinfo($done['handle']);
                if ($info['http_code'] > 199 && $info['http_code'] < 300 )  {

                    $file = curl_multi_getcontent($done['handle']);                     


                    // handle the done request
                    if($file != null && $file != '' && !empty($file) && $file != 'null' )
                    {
                        $parts = parse_url($info['url']);  
                        $filename = basename($parts['path']);  
                        $path_to_file = $directory . '/' . $filename;

                        $ext = pathinfo($filename, PATHINFO_EXTENSION);
                        if ($parent->config->get('config_error_log')) {
                            $parent->log->write('PHP Importer Images: Image extension: ' . $ext);
                        }
                        $ok = TRUE;
                        if( $ext == 'jpg' || $ext == 'jpeg' || $ext == 'png' || $ext == 'gif' ) {
                            $path_to_file = $directory . '/' . $this->clean_filename($filename);
                            $theFileName = $this->clean_filename($filename);
                        }
                        else
                        {           
                            $path_to_file = $directory . '/' . $this->clean_filename($filename .$parts['query']);
                            $theFileName = $this->clean_filename($filename .$parts['query']) . ".jpg";

                            switch ($info['content_type']) {
                                case 'image/jpeg':
                                    $path_to_file = $path_to_file.'.jpg';
                                    $theFileName = $theFileName.'.jpg';
                                    $ok = TRUE;
                                    break;
                                case 'image/gif':
                                    $path_to_file = $path_to_file.'.gif';   
                                    $theFileName = $theFileName.'.gif';
                                    $ok = TRUE;
                                    break;
                                case 'image/png':
                                    $path_to_file = $path_to_file.'.png';
                                    $theFileName = $theFileName.'.png';
                                    $ok = TRUE;
                                    break;
                                default:
                                    $ok = FALSE;
                                break;
                            }
                        }

                        if ($parent->config->get('config_error_log')) {
                            $parent->log->write('PHP Importer Images: Image type: ' . $info['content_type']);
                        }                           

                        if($ok === TRUE)
                        if(file_put_contents($path_to_file, $file) > 0) 
                        {
                            if ($parent->config->get('config_error_log')) {
                                $parent->log->write('PHP Importer Images: Image saved image: ' . $info['url']);
                            }
                            $parent->nr_images_imported++;                      
                        }
                    }
                    unset($file);
                } else {
                    // request failed.  add error handling.
                    if ($parent->config->get('config_error_log')) {
                        $parent->log->write('PHP Importer Images: Failed downloading image: ' . $info['url']);
                    }
                }

                // start a new request (it's important to do this before removing the old one)
                if($t+1 < count($images))   {
                    $t++;
                    $chs[$t] = curl_init();
                    curl_setopt($chs[$t], CURLOPT_URL, $images[$t]['image']);
                    curl_setopt($chs[$t], CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($chs[$t], CURLOPT_CONNECTTIMEOUT, 100);
                    curl_setopt($chs[$t], CURLOPT_TIMEOUT, 100);
                    curl_multi_add_handle($cmh, $chs[$t]);    
                    if ($parent->config->get('config_error_log')) {
                        $parent->log->write('PHP Importer Images: Added to queue image: 147' . $images[$t]['image'] . ' CNT: '. count($chs));
                    }
                }

                // remove the curl handle that just completed
                curl_close($done['handle']);
                curl_multi_remove_handle($cmh, $done['handle']);
                if(($key = array_search($done['handle'], $chs)) !== false) {
                    unset($chs[$key]);
                }
                unset($done);
                clearstatcache();
                if ($parent->config->get('config_error_log')) {
                    $parent->log->write('PHP Importer Images: Removed from queue image 160: ' . $info['url'] .  ' CNT: '. count($chs));
                }
                if($t % 50 == 0)    {
                    $parent->db->query("SELECT 1");
                    if ($parent->config->get('config_error_log')) {
                        $parent->log->write('PHP Importer Images: PING - MYSQL! 165 ');
                    }
                }

            }

        } while ($running);

        if ($parent->config->get('config_error_log')) {
            $parent->log->write('PHP Importer Images: Before images m_CURL_CLOSE !');
        }

        curl_multi_close($cmh);
        //PING
        $parent->db->query("SELECT 1");

        return TRUE;

    } catch(Exception $e) {
        $errstr = $e->getMessage();
        $errline = $e->getLine();
        $errfile = $e->getFile();
        $errno = $e->getCode();
        $parent->session->data['export_error'] = array( 'errstr'=>$errstr, 'errno'=>$errno, 'errfile'=>$errfile, 'errline'=>$errline );
        if ($parent->config->get('config_error_log')) {
            $parent->log->write('PHP ' . get_class($e) . ':  ' . $errstr . ' in ' . $errfile . ' on line ' . $errline);
        }
        return false;
    }

}
...