Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHAR internal corruption (crc32 mismatch) during process fork

Tags:

linux

php

fork

phar

I am developer of ko-worker library. I add feature with phar executable as daemons application. And found strange behavior with phar and process forking undex linux. Each time the master process fork`s more then 1 child i got error like that

include(phar:///opt/www/worker.phar/vendor/path/to/file.php): 
failed to open stream: phar error: internal corruption of phar    

"/opt/www/worker.phar" (crc32 mismatch on file "vendor/path/to/file.php")
in `phar:///opt/www/worker.phar/vendor/composer/ClassLoader.php` line 412

The stub (original stub here) of phar look`s like

#!/usr/bin/env php
<?php
     Phar::mapPhar('worker.phar');
     require_once 'phar://worker.phar/vendor/autoload.php';

     //Execute next going fork code more then one 1 time
     ...
     $pid = pcntl_fork();
     if ($pid == -1) {
         die('could not fork');
     } else if ($pid) {
        // we are the parent
        ...
     } else {
        // we are the child
        ...
        exit(1);
     }

     __HALT_COMPILER();

I do not use cache_list. This happens only if phar is compressed with GZ or BZ2. Phar files without compression do not reproduce this bug. Is any workarounds around it or may be some information about restriction of compressed phars and forked process?

like image 867
Nick Bondarenko Avatar asked Apr 02 '15 12:04

Nick Bondarenko


2 Answers

PHP Phar extension internally opens a Phar file and uses seek/tell/read operations on that descriptor to read the required files from the archive. Because forked processes all use the same descriptor and therefore also share the current file position pointer, then there is a race condition between these operations.

This problem is easily reproducible and happens with or without compression, but compression makes it more likely.

I'm not sure if this is actually a bug, because it is not easy to fix from PHP side and the same kind of problem likely exists for any PHP function, which have an open file descriptor in the background. It's more a problem of the documentation, which does not clearly state, that all the operations on the same Phar file share the same file descriptor in the background, even if it is not obvious from the PHP code.

The fix is to make sure you do not access the Phar before fork() or use some kind of locking mechanism when accessing the same Phar archive from different processes created by fork().

like image 120
Erki Aring Avatar answered Nov 09 '22 02:11

Erki Aring


Seems like a PHP issue, report as a bug at https://bugs.php.net/ with steps to reproduce.

like image 40
mvorisek Avatar answered Nov 09 '22 02:11

mvorisek