protected function fork_work_unit(array $work_unit, $identifier = '', $bucket = self::DEFAULT_BUCKET)
	{
		// prefork callback
		foreach ($this->parent_function_prefork as $function)
		{
			$this->invoke_callback($function, array(), true);
		}

		// init the IPC sockets
		list($socket_child, $socket_parent) = $this->ipc_init();

		// turn off signals temporarily to prevent a SIGCHLD from interupting the parent before $this->forked_children is updated
		pcntl_async_signals(false);

		// spoon!
		$pid = pcntl_fork();

		if ($pid == -1)
		{
			/**
			 * Fork Error
			 */

			$this->log('failed to fork', self::LOG_LEVEL_CRIT);
			return false;
		}
		elseif ($pid)
		{
			/**
			 * Parent Process
			 */

			// keep track of this pid in the parent
			$this->forked_children[$pid] = array(
				'ctime' => time(),
				'identifier' => $identifier,
				'bucket' => $bucket,
				'status' => self::WORKER,
				'socket' => $socket_child,
				'last_active' => microtime(true),
			);
			$this->forked_children_count++;

			// turn back on signals now that $this->forked_children has been updated
			pcntl_async_signals(true);

			// close our socket (we only need the one to the child)
			socket_close($socket_parent);

			// debug logging
			$this->log('forking child ' . $pid . ' for bucket ' . $bucket, self::LOG_LEVEL_DEBUG);

			// parent spawned child callback
			$this->invoke_callback($this->parent_function_fork[$bucket], array($pid, $identifier), true);
		}
		else
		{
			/**
			 * Child Process
			 */

			// free up unneeded parent memory for child process
			$this->work_units = null;
			$this->forked_children = null;
			$this->results = null;

			// set child properties
			$this->child_bucket = $bucket;

			// turn signals on for the child
			pcntl_async_signals(true);

			// close our socket (we only need the one to the parent)
			socket_close($socket_child);

			// re-seed the random generator to prevent clone from parent
			srand();
			mt_srand();

			// child run callback
			$result = $this->invoke_callback($this->child_function_run[$bucket], $work_unit, false);

			// send the result to the parent
			self::socket_send($socket_parent, $result);

			// delay the child's exit slightly to avoid race conditions
			usleep(500);

			// exit after we complete one unit of work
			exit;
		}

		return $pid;
	}
protected function fork_work_unit(array $work_unit, $identifier = '', $bucket = self::DEFAULT_BUCKET)
	{
		// prefork callback
		foreach ($this->parent_function_prefork as $function)
		{
			$this->invoke_callback($function, array(), true);
		}

		// init the IPC sockets
		list($socket_child, $socket_parent) = $this->ipc_init();

		// turn off signals temporarily to prevent a SIGCHLD from interupting the parent before $this->forked_children is updated
		pcntl_async_signals(false);

		// spoon!
		$pid = pcntl_fork();

		if ($pid == -1)
		{
			/**
			 * Fork Error
			 */

			$this->log('failed to fork', self::LOG_LEVEL_CRIT);
			return false;
		}
		elseif ($pid)
		{
			/**
			 * Parent Process
			 */

			// keep track of this pid in the parent
			$this->forked_children[$pid] = array(
				'ctime' => time(),
				'identifier' => $identifier,
				'bucket' => $bucket,
				'status' => self::WORKER,
				'socket' => $socket_child,
				'last_active' => microtime(true),
			);
			$this->forked_children_count++;

			// turn back on signals now that $this->forked_children has been updated
			pcntl_async_signals(true);

			// close our socket (we only need the one to the child)
			socket_close($socket_parent);

			// debug logging
			$this->log('forking child ' . $pid . ' for bucket ' . $bucket, self::LOG_LEVEL_DEBUG);

			// parent spawned child callback
			$this->invoke_callback($this->parent_function_fork[$bucket], array($pid, $identifier), true);
		}
		else
		{
			/**
			 * Child Process
			 */

			// free up unneeded parent memory for child process
			$this->work_units = null;
			$this->forked_children = null;
			$this->results = null;

			// set child properties
			$this->child_bucket = $bucket;

			// turn signals on for the child
			pcntl_async_signals(true);

			// close our socket (we only need the one to the parent)
			socket_close($socket_child);

			// re-seed the random generator to prevent clone from parent
			srand();
			mt_srand();

			// child run callback
			$result = $this->invoke_callback($this->child_function_run[$bucket], $work_unit, false);

			// send the result to the parent
			self::socket_send($socket_parent, $result);

			// delay the child's exit slightly to avoid race conditions
			usleep(500);

			// exit after we complete one unit of work
			exit;
		}

		return $pid;
	}
protected function fork_work_unit ( array $ work_unit , $ identifier = '' , $ bucket = self :: DEFAULT_BUCKET ) { // prefork callback foreach ( $ this -> parent_function_prefork as $ function ) { $ this -> invoke_callback ( $ function , array ( ) , true ) ; } // init the IPC sockets list ( $ socket_child , $ socket_parent ) = $ this -> ipc_init ( ) ; // turn off signals temporarily to prevent a SIGCHLD from interupting the parent before $this->forked_children is updated pcntl_async_signals ( false ) ; // spoon! $ pid = pcntl_fork ( ) ; if ( $ pid == - 1 ) { /**
			 * Fork Error
			 */ $ this -> log ( 'failed to fork' , self :: LOG_LEVEL_CRIT ) ; return false ; } elseif ( $ pid ) { /**
			 * Parent Process
			 */ // keep track of this pid in the parent $ this -> forked_children [ $ pid ] = array ( 'ctime' => time ( ) , 'identifier' => $ identifier , 'bucket' => $ bucket , 'status' => self :: WORKER , 'socket' => $ socket_child , 'last_active' => microtime ( true ) , ) ; $ this -> forked_children_count ++ ; // turn back on signals now that $this->forked_children has been updated pcntl_async_signals ( true ) ; // close our socket (we only need the one to the child) socket_close ( $ socket_parent ) ; // debug logging $ this -> log ( 'forking child ' . $ pid . ' for bucket ' . $ bucket , self :: LOG_LEVEL_DEBUG ) ; // parent spawned child callback $ this -> invoke_callback ( $ this -> parent_function_fork [ $ bucket ] , array ( $ pid , $ identifier ) , true ) ; } else { /**
			 * Child Process
			 */ // free up unneeded parent memory for child process $ this -> work_units = null ; $ this -> forked_children = null ; $ this -> results = null ; // set child properties $ this -> child_bucket = $ bucket ; // turn signals on for the child pcntl_async_signals ( true ) ; // close our socket (we only need the one to the parent) socket_close ( $ socket_child ) ; // re-seed the random generator to prevent clone from parent srand ( ) ; mt_srand ( ) ; // child run callback $ result = $ this -> invoke_callback ( $ this -> child_function_run [ $ bucket ] , $ work_unit , false ) ; // send the result to the parent self :: socket_send ( $ socket_parent , $ result ) ; // delay the child's exit slightly to avoid race conditions usleep ( 500 ) ; // exit after we complete one unit of work exit ; } return $ pid ; }
Fork one child with one unit of work

Given a work unit array, fork a child and hand
off the work unit to the child.

@param array  $work_unit  An array of work to process.
@param string $identifier A unique identifier for this work.
@param int    $bucket     The bucket to use.
@return mixed the child pid on success or boolean false on failure
Fork one child with one unit of work