83 votes

Comment attraper l'erreur fatale : Le temps d'exécution maximal de 30 secondes a été dépassé en PHP

Je me suis amusé avec un système que je développe et j'ai réussi à provoquer ça :

Erreur fatale : Le temps d'exécution maximum de 30 secondes a été dépassé

Cela s'est produit lorsque je faisais quelque chose d'irréaliste, mais néanmoins cela pourrait se produire avec un utilisateur.

Quelqu'un sait-il s'il existe un moyen d'attraper cette exception ? Je me suis renseigné, mais tout le monde semble suggérer d'augmenter le temps imparti.

1 votes

Je crois qu'une fois le temps d'exécution dépassé, le script est terminé. Dans ce cas, le script qui aurait pu attraper l'exception a déjà été tué.

0 votes

Les erreurs fatales ne peuvent pas être attrapées (ce ne sont pas des exceptions) ou traitées. Vous pouvez seulement gérer la fin de script de manière gracieuse en enregistrement d'une fonction d'arrêt mais le script se terminera après.

0 votes

4voto

user3901681 Points 1

Il existe un moyen un peu délicat de traiter "Fatal error : Temps d'exécution maximum de 30 secondes dépassé" comme exception dans certains cas :

function time_sublimit($k = 0.8) {
    $limit = ini_get('max_execution_time'); // changes even when you set_time_limit()
    $sub_limit = round($limit * $k);
    if($sub_limit === 0) {
        $sub_limit = INF;
    }
    return $sub_limit;
}

Dans votre code, vous devez mesurer le temps d'exécution et lancer l'exception avant que le timeout ne déclenche une erreur fatale. $k = 0.8 est un 80% du temps d'exécution autorisé, donc vous avez 20% du temps pour gérer l'exception.

try{
    $t1 = time(); // start to mesure time.
    while (true) { // put your long-time loop condition here
        time_spent = time() - $t1;
        if(time_spent >= time_sublimit()) {
            throw new Exception('Time sublimit reached');
        }
        // do work here
    }
} catch(Exception $e) {
    // catch exception here
}

4voto

Gregory Lewis Points 440

J'ai trouvé cette idée en me basant sur la réponse de @pinkal-vansia. Donc je ne revendique pas une réponse originale, mais une réponse avec une application pratique. J'avais besoin d'un moyen pour que la page se rafraîchisse elle-même en cas de dépassement de délai. Puisque j'ai observé suffisamment de timeouts de mon script cURL pour savoir que le code fonctionne, mais que parfois, pour une raison quelconque, il ne parvient pas à se connecter au serveur distant, ou à lire complètement le html servi, et que lors du rafraîchissement le problème disparaît, je suis d'accord pour que le script se rafraîchisse lui-même pour "soigner" une erreur de timeout d'exécution maximale.

<?php //script name: scrape_script.php

ini_set('max_execution_time', 300);

register_shutdown_function('shutdown');

function shutdown() 
{ 
    ?><meta http-equiv="refresh" content="0; url=scrape_script.php"><?php
    // just do a meta refresh. Haven't tested with header location, but
    // this works fine.
}

Pour information, 300 secondes n'est pas trop long pour le script de scraping que j'exécute, qui prend juste un peu moins que cela pour extraire les données des types de pages que je scrape. Parfois, le temps est dépassé de quelques secondes seulement en raison d'irrégularités de connexion. Sachant que ce sont les temps de connexion qui échouent parfois, plutôt que le traitement du script, il est préférable de ne pas augmenter le timeout, mais plutôt de rafraîchir automatiquement la page et de réessayer.

3voto

J'ai été confronté à un problème similaire et voici comment je l'ai résolu :

<?php
function shutdown() {
    if (!is_null($error = error_get_last())) {
        if (strpos($error['message'], 'Maximum execution time') === false) {
            echo 'Other error: ' . print_r($error, true);
        } else {
            echo "Timeout!\n";
        }
    }
}

ini_set('display_errors', 0);
register_shutdown_function('shutdown');
set_time_limit(1);

echo "Starting...\n";
$i = 0;
while (++$i < 100000001) {
    if ($i % 100000 == 0) {
        echo ($i / 100000), "\n";
    }
}
echo "done.\n";
?>

Ce script, tel quel, va imprimer Timeout! à la fin.

Vous pouvez modifier la ligne $i = 0; a $i = 1 / 0; et ça va s'imprimer :

Other error: Array
(
    [type] => 2
    [message] => Division by zero
    [file] => /home/user/test.php
    [line] => 17
)

Références :

-7voto

Subdigger Points 1307

Mettez ceci au début du fichier php

<?php
    set_time_limit(0);

EDIT 1

mais vérifiez d'abord s'il n'y a pas de code comme celui-ci :

while (1=1) {
  echo '=)';
}

EDIT 2

pour attraper cette erreur, regardez set_error_handler

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X