21

Problem

When I execute the following code (I'm calling a stored procedure with 5 IN parameters and 1 OUT parameter)

$conn->query("SET @res = ''");

$mysqli=$conn;
if (!($stmt = $mysqli->prepare("CALL retrieve_matches(5,3, 16, 2, false, @res)"))) {
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

if (!$stmt->execute()) {
    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}

do {
    if ($res = $stmt->get_result()) { //Apache crash on this call
        printf("---\n");
        var_dump(mysqli_fetch_all($res));
        mysqli_free_result($res);
    } else {
        if ($stmt->errno) {
            echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
        }
    }
} while ($stmt->more_results() && $stmt->next_result());

apache is crashing with error:

AH00428: Parent: child process 9628 exited with status 255 -- Restarting.

What I tried

  1. This code is working fine and it's returning correctly the results:
$conn->query("SET @res = ''");
$res=$conn->query("CALL retrieve_matches(5,3, 16, 2, false, @res)");
var_dump($res->fetch_assoc());

NOTE: The same code above that make Apache crashing is working correctly if I just change the number in input of the stored procedure like:

if (!($stmt = $mysqli->prepare("CALL retrieve_matches(5,6, 16, 2, false, @res)"))) {
  1. Tried from MySQl workbench and both calls are working fine.
  2. I'm using WAMP 64b on a WIN7 Enterprise 64b, I tried with WAMP 32b but got same problem.
  3. I checked windows event and I found httpd.exe is crashing caused by php5ts.dll
  4. If you search for "httpd.exe php5ts.dll" on google you can find a lot of people incountering this problem. But I didn't find a solution for WAMP...
  5. Tried with AMPPS, exact same problem

PHP Error Log

[10-Jul-2015 15:30:03 UTC] PHP Warning:  PHP Startup: Unable to load dynamic library 'C:/Program Files/wamp/bin/php/php5.5.12/ext/php_ldap.dll' - Impossibile trovare il modulo specificato.

 in Unknown on line 0

[10-Jul-2015 15:30:04 UTC] PHP Warning:  PHP Startup: Unable to load dynamic library 'C:/Program Files/wamp/bin/php/php5.5.12/ext/php_intl.dll' - Impossibile trovare il modulo specificato.

APACHE error log:

[Tue Jul 14 15:02:13.038276 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00428: Parent: child process 9448 exited with status 255 -- Restarting.
[Tue Jul 14 15:02:13.324305 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00455: Apache/2.4.9 (Win32) PHP/5.5.12 configured -- resuming normal operations
[Tue Jul 14 15:02:13.329306 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00456: Apache Lounge VC11 Server built: Mar 16 2014 12:13:13
[Tue Jul 14 15:02:13.329306 2015] [core:notice] [pid 7044:tid 404] AH00094: Command line: 'C:\\Program Files\\wamp\\bin\\apache\\apache2.4.9\\bin\\httpd.exe -d C:/Program Files/wamp/bin/apache/apache2.4.9'
[Tue Jul 14 15:02:13.352308 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00418: Parent: Created child process 3140
[Tue Jul 14 15:02:14.528388 2015] [mpm_winnt:notice] [pid 3140:tid 332] AH00354: Child: Starting 64 worker threads.

I'm really lost here, where should I look for the issue? Thanks very much for your help

EDIT

I realized that the stored procedure "retrieve_matches" is calling different stored procedure in function of the changed value. I debugged the stored procedure "retrieve_standalone" that is the one that make Apache crashing. This procedure is doing select/insert, I checked and the insert are made correctly. BUT inside "retrieve_standalone" I'm using a cursor in a weird way:

declare bNoMoreRows bool default false;
declare tmp_cursor cursor for
    select comp_id from to_match; -- to_match is a temporary table
declare continue handler for not found set bNoMoreRows := true;

if I don't open the cursor

open tmp_cursor;

everything is working fine!! So I guess I found the issue, now: how can I solve it?

Mousey
  • 1,793
  • 15
  • 34
Stefano Giacone
  • 1,824
  • 2
  • 23
  • 46
  • ERR_CONNECTION_RESET means this is a browser issue but not the coding issue – Chandu9999 Jul 07 '15 at 21:50
  • $stmt->get_result()->fetch_assoc(); assumes that the query returned at least one row. Does it? – Severian Jul 07 '15 at 21:54
  • how can be a browser issue if the first query is working? – Stefano Giacone Jul 07 '15 at 21:54
  • Yes $stmt->get_result()->fetch_assoc(); return at least one row, in fact the first query is returning the data of the first row – Stefano Giacone Jul 07 '15 at 21:55
  • ERR_CONNECTION_RESET is a chrome issue and has nothing to do with your code, you can see all kinds of answers about that one. I would set a true false flag on that stmt->execute and make double sure you are returning something. – Severian Jul 07 '15 at 21:58
  • Did you try searching "ERR_CONNECTION_RESET mysqli error" before coming and asking your question here? – Sakamaki Izayoi Jul 07 '15 at 22:26
  • Could you just check if all of the intermediate objects are available and split the concatenation of methods in to separate object vars? Like `if $stmt !== false { $ret = $stmt->get_result(); if ( $ret !== false ... ` – Axel Amthor Jul 08 '15 at 06:42
  • yeah I did, but anyway Apache should not crash. It's probably a problem with the drivers, my concern is that it's happening only on that query. – Stefano Giacone Jul 08 '15 at 07:12
  • so It's dying on the `if (!$stmt->execute()) {` line? – iam-decoder Jul 10 '15 at 16:27
  • put in a bunch of `exit('here');`s on each line and slowly remove from the top down and see where exactly Apache crashes so that we can help you better. – iam-decoder Jul 10 '15 at 16:29
  • Right. The crash happen on the "get_result()" line – Stefano Giacone Jul 11 '15 at 04:56
  • I would try to execute the sql from command line using php exec see what happen ,then continue the research – talsibony Jul 12 '15 at 11:54
  • It is 'interesting' that the code works if you change the input values to the procedure `retrieve_matches`. Are there different logic paths in there that can cause 'something unusual to happen' such as not return a result etc.? – Ryan Vincent Jul 13 '15 at 09:45
  • It's really weird... that parameter simply change a "WHERE" clause inside the stored procedure. Moreover from MySQL workbench I can't find any differences... – Stefano Giacone Jul 13 '15 at 11:35
  • Do you get ANYTHING in the PHP error log? And what do you get in the Apache log? – nl-x Jul 14 '15 at 12:37
  • Log added in the question – Stefano Giacone Jul 14 '15 at 13:20
  • @StefanoGiacone Check http://stackoverflow.com/questions/26100326/php-mysql-connect-child-process-exited-with-status-255-restarting to see if this a lead – nl-x Jul 14 '15 at 13:30
  • @StefanoGiacone Also tell me if you have php_intl.dll and php_ldap.dll in your EXT directory. It *could* be that these startup errors affect PHP stability and cause your crashes. It could very well be that php_intl.dll / php_ldap.dll ARE present btw. Just tell me what is your case. – nl-x Jul 14 '15 at 13:31
  • Just checked and I found them in the EXT directory. php_intl.dll / php_ldap.dll ARE present. – Stefano Giacone Jul 14 '15 at 13:37
  • @StefanoGiacone locate dll files starting with icu, and copy them to the Apache bin directory. (So I'm talking about icu*.dll files) And restart Apache. I think this should remove the startup errors you see in the PHP log file. Maybe it will also solve your problem with crashes. Please tell me if you still get startup errors, and if you still get crashes – nl-x Jul 14 '15 at 13:39
  • this solved the warnings (thanks). But not the crashes :( but I have a lead, I'll update the question – Stefano Giacone Jul 14 '15 at 13:48
  • @StefanoGiacone Please also copy php5apache.dll and libmysql.dll to your Apache bin directory, as mentioned in the link I provided earlier. And then restart Apache, and check again. – nl-x Jul 14 '15 at 13:51
  • In the php folder I found php5apache2_4.dll but not php5apache.dll. I can't find libmysqli.dll anywhere in the wamp installation. I did find libmysql.dll in the mysql/lib folder. I copied in the Apache folder, restarted but still crash. where can I find libmysqli.dll? Thanks for all you help, really appreciated. – Stefano Giacone Jul 14 '15 at 14:01
  • @StefanoGiacone Sorry, I think I am wrong about libmysqli.dll. My bad. – nl-x Jul 14 '15 at 14:08
  • @StefanoGiacone Last thing I can think of: have you checked your MySQL .err log file ? On my computer I find it here: C:\ProgramData\MySQL\MySQL Server 5.5\data – nl-x Jul 14 '15 at 15:02

6 Answers6

6

If php5ts.dll, or any other part of apache crashes in a reproducible way every time you run a short script, you have most likely hit a bug in php. Especially if you run an up-to-date apache with a recent php-version downloaded from php.net you have a very good chance of getting support from the PHP team. So read through https://bugs.php.net/how-to-report.php, see if you can reproduce the crash when running the script without apache (in a separate script on the cli using php.exe) and generate a backtrace which you can then submit as a bug.

Bugs like these can sometimes be worked around but rarely be fixed from the context of your script. PHP should never crash the webserver and if it does this reproducibly a bug should be filed so it can be fixed

Sjon
  • 4,605
  • 6
  • 24
  • 42
  • Maybe, but If you search for "httpd.exe php5ts.dll" on google you can find a lot of people incountering this problem. Not sure if I should open a bug... – Stefano Giacone Jul 13 '15 at 09:33
  • If you have a reproducible testcase you have a pretty good chance, were you able to generate a proper backtrace? – Sjon Jul 13 '15 at 09:36
5

I find out how to reproduce it, I believe it's a php/apache bug

PHP code:

if (!($stmt = $mysqli->prepare("CALL test()"))) {
    echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}

if (!$stmt->execute()) {
    echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}

do {
    if ($res = $stmt->get_result()) {
        printf("---\n");
        //var_dump(mysqli_fetch_all($res));
        var_dump($res->fetch_assoc());
        mysqli_free_result($res);
    } else {
        if ($stmt->errno) {
            echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
        }
    }
} while ($stmt->more_results() && $stmt->next_result());

Store procedure code:

CREATE DEFINER=`root`@`localhost` PROCEDURE `test`()
BEGIN
declare test_var varchar(100) default "ciao";
declare bNoMoreRows bool default false;
declare test_cursor cursor for
    select id from tmp_folder;
declare continue handler for not found set bNoMoreRows := true;

create temporary table tmp_folder select "test" as id;

open test_cursor;

fetch test_cursor into test_var;

close test_cursor;

select test_var;

drop temporary table if exists tmp_folder;

END

Bug opened: Apache: https://bz.apache.org/bugzilla/show_bug.cgi?id=58136

Php: https://bugs.php.net/bug.php?id=70073

Stefano Giacone
  • 1,824
  • 2
  • 23
  • 46
  • $stmt->get_result() gets me "Call to undefined method mysqli_stmt::get_result()" - http://stackoverflow.com/questions/8321096/call-to-undefined-method-mysqli-stmtget-result – LSerni Jul 17 '15 at 10:27
3

Another one bites the dust here. Just dropped in to offer a workaround.

SP with a cursor only crashes when prepare() is used.

If you change it to multi_query() call it would work. A simple reproducible POC

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = mysqli_connect('127.0.0.1','user','pass','db');

$mysqli->query("DROP PROCEDURE IF EXISTS mysqli_crash");
$mysqli->query("CREATE PROCEDURE mysqli_crash ()
BEGIN
    DECLARE col TEXT;
    DECLARE res CURSOR FOR SELECT 1 from dual;
    OPEN res;
    FETCH res INTO col;
    CLOSE res;
    SELECT 1 from dual;
END;");

echo  "--- multi_query ---\n";

$mysqli->multi_query("call mysqli_crash()");
$result = $mysqli->store_result();
echo json_encode($result->fetch_all(MYSQLI_ASSOC)),"\n";
$mysqli->next_result();

echo  "--- prepare ---\n";

$stmt = $mysqli->prepare("call mysqli_crash()");
$stmt->execute();
$result = $stmt->get_result();
echo json_encode($result->fetch_all(MYSQLI_ASSOC)),"\n";
$stmt->next_result();

Yes, prepare is preferred but if your stored procedure is using a cursor there is no choice.

Your Common Sense
  • 152,517
  • 33
  • 193
  • 313
1

I think you are confusing $conn and $stmt. Here is what I have. (It gathers the result into $out.)

if ($conn->multi_query($call)) {
    $raa = array();
    do {
        /* store first result set */
        if ($result = $conn->use_result()) {
            while ($row = $result->fetch_row()) {
                $raa[] = $row;
                printf("+\n");
            }
            $result->close();
        }
        $out[] = $raa;
        /* print divider */
        if ($conn->more_results()) {
            printf("-----------------\n");
        }
    } while ($conn->next_result());
}
else
    echo "err";
Rick James
  • 106,233
  • 9
  • 103
  • 171
  • There are no problems with my code. It was copy pasted from PHP documentation. Moreover it's working for different values passed to the stored procedure... – Stefano Giacone Jul 13 '15 at 09:33
  • 1
    It is not a confusion on the @StefanoGiacone part. It's a confusion on mysqli part. SP without a cursor works with both prepare and multiquery but SP using a cursor works with multi_query but crashes with prepare. Still. – Your Common Sense Apr 18 '20 at 15:03
  • So you can rather position your answer as a workaround – Your Common Sense Apr 18 '20 at 15:04
1

Apparently there's a bit of buck passing - i.e. scaricabarile - between PHP guys and MySQLi guys.

What seems to be happening is that MySQLi reacts in an "improper" way, and return an unexpected value (I'd bet a small sum on it being a NULL) to PHP, which duly coredumps. This behaviour is documented and the verdict from PHPland is: "Not a [PHP] bug". On their side, the MySQLi guys maintain that it's PHP which is not correctly checking the returned result. And that 'improper' results depended on your query anyway.

So I'm going out on a limb and supposing that yours is the same problem of "communication difficulties", so the problem becomes: "Your query forces MySQLi to drop/reconnect". Why is that so? Apparently (some) stored procedures require mysqli_multi_query in order to behave properly.

And mysqli_multi_query is not compatible with mysqli_prepare.

So I'd suggest trying without preparing the query, and running it with mysqli_multi_query.

$conn->query("SET @res = ''");
$conn->multi_query("CALL retrieve_matches(5,3, 16, 2, false, @res)");

do {
    if ($result = $conn->store_result()) {
        while ($row = $result->fetch_row()) {
            var_dump($row);
        }
        $result->free();
    }
} while ($conn->more_results() && $conn->next_result());

With this code, your test case gets me, as expected,

array(1) {
  [0] =>
  string(4) "test"
}
Community
  • 1
  • 1
LSerni
  • 49,775
  • 9
  • 56
  • 97
  • Thanks, I can confirm you (as you can read from my question "What I tried, point 1") that if I don't prepare the query, everythng is working correctly. Too bad that they're not agreeing on a solution... – Stefano Giacone Jul 17 '15 at 13:41
-2

Try changing your server stack. Either upgrade WAMP or run your code in a different environment. This question suggests there is a bug in WAMP that will cause Apache to throw the 255 error

php -> mysql_connect -> child process exited with status 255 -- Restarting

Community
  • 1
  • 1
Mike Miller
  • 2,686
  • 1
  • 18
  • 30