dpzjl68484 2015-09-05 04:33
浏览 77
已采纳

cURL冻结Apache并因404错误而超时

I have a really strange issue with a cURL request. Basically I have some code that I use to wrap a legacy PHP app on Symfony2 (http://symfonybricks.com/it/brick/wrap-legacy-php-code-by-a-symfony2-application). They are basic cURL commands that should pull a webpage and display it. However, I have noticed the following :

  • If I make a query to an existing file, it's working fine
  • If I make a query to a file that doesn't exist, cURL time out (Because I have set up a time out of 8sec), and during that time, it freeze the whole server, I can't access my website from any other devices until it actually time out.

Here's my code :

/**
 * @Route("/", defaults={"controller" = "index.php", "controller2" = "", "controller3" = ""})
 * @Route("/{controller}", defaults={"controller2" = "index.php", "controller3" = ""})
 * @Route("/{controller}/", defaults={"controller2" = "index.php", "controller3" = ""})
 * @Route("/{controller}/{controller2}", defaults={"controller3" = ""})
 * @Route("/{controller}/{controller2}/", defaults={"controller3" = ""})
 * @Route("/{controller}/{controller2}/{controller3}", defaults={"controller3" = "index.php"})
 */
public function getLegacyResourceAction($controller, $controller2, $controller3, Request $request)

{


    $path_to_legacy_code = "http://XXX/";

    $originalController = $request->getPathInfo();

    $originalQueryString = $request->getQueryString();

   $url = "{$path_to_legacy_code}{$originalController}?{$originalQueryString}";

    //open connection

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

    curl_setopt($ch, CURLOPT_HEADER, false);

    curl_setopt($ch, CURLOPT_VERBOSE, 1);

    curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);

    //Timeout
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
    curl_setopt($ch, CURLOPT_TIMEOUT, 8); 
    curl_setopt($ch,  CURLOPT_MAXREDIRS, 5);       

    $stderr = fopen("{$this->container->getParameter('kernel.root_dir')}/logs/curl.txt", "a");
    curl_setopt($ch, CURLOPT_STDERR, $stderr);


    //echo "Login stuff in ".$this->container->getParameter('kernel.root_dir')."/logs/curl.txt";


    curl_setopt($ch, CURLOPT_COOKIESESSION, 0);

    curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');

    curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');  

    $result = curl_exec($ch);


    if (false === $result) {
        echo curl_error($ch);
        exit;
    }

    curl_close($ch);
    fclose($stderr);

    $Response = new Response($result);


    return $Response;

Here's the log I'm getting from a valid response :

* About to connect() to www.xxx.com port 80 (#0)
*   Trying 178.32.223.113...
* connected
* Connected to www.xxx.com (178.32.223.113) port 80 (#0)
> GET /web/legacy/index.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefo$
Host: www.xxx.com
Accept: */*
Cookie: idto=116; PHPSESSID=a159rcjvh0fk6otukqqq9bkrd5

* additional stuff not fine transfer.c:1037: 0 0
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Sat, 05 Sep 2015 04:26:32 GMT
< Server: Apache/2.2.22 (Debian)
< X-Powered-By: PHP/5.5.28-1~dotdeb+7.1
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html
<
* Connection #0 to host www.xxx.com left intact
* Closing connection #0

And here's the code from an invalid response :

* About to connect() to www.xxx.com port 80 (#0)
*   Trying 178.32.223.113...
* connected
* Connected to www.xxx.com (178.32.223.113) port 80 (#0)
> GET /web/legacy/whatever.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefo$
Host: www.xxx.com
Accept: */*
Cookie: idto=116; PHPSESSID=a159rcjvh0fk6otukqqq9bkrd5

* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* Operation timed out after 8001 milliseconds with 0 bytes received
* Closing connection #0
* About to connect() to www.xxx.com port 80 (#0)
*   Trying 178.32.223.113...
* connected
* Connected to www.xxx.com (178.32.223.113) port 80 (#0)
> GET /web/legacy/legacy/whatever.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefo$
Host: www.xxx.com
Accept: */*
Cookie: idto=116; PHPSESSID=a159rcjvh0fk6otukqqq9bkrd5

* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* additional stuff not fine transfer.c:1037: 0 0
* Operation timed out after 8001 milliseconds with 0 bytes received
* Closing connection #0
* About to connect() to www.xxx.com port 80 (#0)
*   Trying 178.32.223.113...
* connected
* Connected to www.xxx.com (178.32.223.113) port 80 (#0)
> GET /web/legacy/legacy/legacy/whatever.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefo$
Host: www.xxx.com
Accept: */*

Everything that's bellow curl_exec($ch); is not executed until it time out, not giving me a chance to check for a 404 error or something. I've been searching for days, no luck so far.

Thanks a lot !

EDIT :

Okay, so I solved the issue by removing this line :

curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');

Now it give a proper 404 error. I have no idea why it's working without this line. The problem is, without this line I'm breaking some session stuff from my legacy code !

EDIT 2 :

I've changed :

  • curl_setopt($ch, CURLOPT_COOKIESESSION, 0);

to

  • curl_setopt($ch, CURLOPT_COOKIESESSION, 1);

And now it's working fine with 404 error and my session. I have NO IDEA why.

EDIT 3 :

Okay, I thing I finally understand what's going on :

  • On every cURL request, it write on the cookie.txt file
  • If someone query a 404 url, before the time out, it file lock the cookie.txt file, and that's why the whole thing seems to be frozen.

As of my understanding, the best solution would be to generate a different cookie.txt file for each user, preventing a file lock.

  • 写回答

1条回答 默认 最新

  • ds20021205 2015-09-05 04:46
    关注

    I finally got to the bottom of this, turns out I had two issues :

    • No timeout configured, so if I'd try to query a non-existing webpage, it would loop indefinitely.
    • I was using the same cookies file for everyone, and if someone was stuck in such loop as mentionned before, it would file lock the cookie file, preventing other users to access the site.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 求数学坐标画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站