<commit_before><?php

namespace Vatson\Callback;

use Vatson\Callback\Exception\ExceptionDataHolder;
use Vatson\Callback\Exception\IsolatedCallbackExecutionException;
use UniversalErrorCatcher_Catcher as ErrorCatcher;

/**
 * @author <NAME> <<EMAIL>>
 * @since 9/26/12
 */
class IsolatedCallback
{
    /**
     * @var callable
     */
    protected $callback;

    /**
     * @var resource
     */
    protected $shared_memory_segment;

    /**
     * @var int
     */
    protected static $SEGMENT_VAR_ID = 1;

    /**
     * @param callable $callback
     */
    public function __construct($callback)
    {
        if (!function_exists('shm_attach')) {
            throw new \RuntimeException('You need to enabled Shared Memory System V(see more "Semaphore")');
        }

        if (!function_exists('pcntl_fork')) {
            throw new \RuntimeException('You need to enable PCNTL');
        }

        if (!is_callable($callback)) {
            throw new \InvalidArgumentException('Given callback is not callable');
        }

        $this->callback = $callback;
        $this->shared_memory_segment = shm_attach(time() + rand(1, 1000));
    }

    /**
     * Calls a callback in a separate fork and returns the received result
     *
     * @throws \RuntimeException when fork can not be created
     *
     * @return mixed
     */
    public function __invoke()
    {
        $arguments = func_get_args();

        switch ($pid = pcntl_fork()) {
            case -1:
                throw new \RuntimeException();
            case 0:
                $this->registerChildShutdown();
                $this->handleChildProcess($arguments);
                exit;
            default:
                return $this->handleParentProcess();
        }
    }

    /**
     * Avoids the closing of resources in child process
     */
    protected function registerChildShutdown()
    {
        (new ErrorCatcher)
            ->registerCallback(function($e) {
                $this->sendChildExecutionResult(new ExceptionDataHolder($e));
            })
            ->start();

        register_shutdown_function(function () {
            posix_kill(getmypid(), SIGKILL);
        });

    }

    /**
     * @throws \Exception when child process ends with an Exception
     *
     * @return mixed
     */
    protected function handleParentProcess()
    {
        pcntl_wait($status);
        $result = $this->receiveChildExecutionResult();

        if ($result instanceof ExceptionDataHolder) {
            throw new IsolatedCallbackExecutionException($result);
        }

        return $result;<commit_msg>[hot-fix] BC for php 5.3.x<commit_after><?php

namespace Vatson\Callback;

use Vatson\Callback\Exception\ExceptionDataHolder;
use Vatson\Callback\Exception\IsolatedCallbackExecutionException;
use UniversalErrorCatcher_Catcher as ErrorCatcher;

/**
 * @author <NAME> <<EMAIL>>
 * @since 9/26/12
 */
class IsolatedCallback
{
    /**
     * @var callable
     */
    protected $callback;

    /**
     * @var resource
     */
    protected $shared_memory_segment;

    /**
     * @var int
     */
    protected static $SEGMENT_VAR_ID = 1;

    /**
     * @param callable $callback
     */
    public function __construct($callback)
    {
        if (!function_exists('shm_attach')) {
            throw new \RuntimeException('You need to enabled Shared Memory System V(see more "Semaphore")');
        }

        if (!function_exists('pcntl_fork')) {
            throw new \RuntimeException('You need to enable PCNTL');
        }

        if (!is_callable($callback)) {
            throw new \InvalidArgumentException('Given callback is not callable');
        }

        $this->callback = $callback;
        $this->shared_memory_segment = shm_attach(time() + rand(1, 1000));
    }

    /**
     * Calls a callback in a separate fork and returns the received result
     *
     * @throws \RuntimeException when fork can not be created
     *
     * @return mixed
     */
    public function __invoke()
    {
        $arguments = func_get_args();

        switch ($pid = pcntl_fork()) {
            case -1:
                throw new \RuntimeException();
            case 0:
                $this->registerChildShutdown();
                $this->handleChildProcess($arguments);
                exit;
            default:
                return $this->handleParentProcess();
        }
    }

    /**
     * Avoids the closing of resources in child process
     */
    protected function registerChildShutdown()
    {
        $catcher = new ErrorCatcher;
        $catcher->registerCallback(function ($e) {
            $this->sendChildExecutionResult(new ExceptionDataHolder($e));
        });
        $catcher->start();

        register_shutdown_function(function () {
            posix_kill(getmypid(), SIGKILL);
        });

    }

    /**
     * @throws \Exception when child process ends with an Exception
     *
     * @return mixed
     */
    protected function handleParentProcess()
    {
        pcntl_wait($status);
        $result = $this->receiveChildExecutionResult();

        if ($result instanceof ExceptionDataHolder) {
            throw new IsolatedCallbackExecutionException($result);
        }

        return $result;
{'fraction_non_alphanumeric': 0.11055948061867481, 'fraction_numerical': 0.005346572465151804, 'mean_word_length': 2.090265486725664, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6188997', 'n_tokens_mistral': 1473, 'n_tokens_neox': 1385, 'n_words': 335}