Segfault bei PHPUnit vermeiden
Wir führen unsere Unittests automatisiert beim Push auf das Git-Repository mit Jenkins aus. Bevor Änderungen auf dem Livesystem eingespielt werden dürfen ist ein “grüner Build” zwingend erforderlich. Bei größeren Projekten kam es bei der Ausführung von PHPUnit immer wieder zu Segmentation Faults mit exec returned: 139
. Beim zweiten Anlauf funktionierte es dann meistens, aber es ist natürlich sehr lästig, weil dadurch bei einer Dauer von ca. 30 Minuten für einen vollständigen Build das Livestellen unnötig verzögert wird.
Im Netz kursieren teils abenteuerliche Lösungen, die beispielsweise den automatischen Neustart von PHPUnit bei einem Segfault favourisieren. Klar, das ist besser als nichts, aber behebt das Problem nun mal nicht. Interessant fand ich daher den dritten Kommentar zu oben genanntem Artikel:
In phpunit you can do:
phpunit -d zend.enable_gc=0
Bei meinem ersten Versuch mit deaktivierter Garbage
Collection wurde natürlich das
memory_limit
überschritten. Eine Erhöhung auf 1,5GB löste zwar das Problem mit dem Limit,
jedoch brach daraufhin PHPUnit bei der Erzeugung des Clover-Reports
unvermittelt ab. Diesmal mit exec returned: 143
. Google förderte leider kaum
brauchbare Ergebnisse zutage, jedoch lag die Vermutung nahe, dass es eben nicht
so optimal ist, die Garbage Collection für den kompletten PHPUnit-Lauf zu
deaktivieren.
Daraufhin haben wir eine eigene Zwischenklasse zwischen
PHPUnit_Framework_TestCase
und unsere TestCases geschoben, in der die Garbage
Collection explizit gesteuert wird. Vor jedem Test wird die GC explizit mit gc_collect_cycles()
aufgerufen, anschließend für den Test deaktiviert und nach dem Test wieder
aktiviert:
Dies funktioniert jetzt seit einigen Tagen recht gut. Ob das Problem damit wirklich aus der Welt ist, wird sich in den nächsten Wochen zeigen!