Skip to content

PHP: Support pcntl by supporting C fork() #595

@adamziel

Description

@adamziel

Some PHP packages call pcntl_fork(). It is, at the moment, unclear whether any WordPress-critical ones require the pcntl extension. Neither wp-cli nor phpunit list pcntl as one of the required extensions – perhaps pcntl_fork is not a high priority for Playground, then?

What is pcntl?

Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. Process Control should not be enabled within a web server environment and unexpected results may happen if any Process Control functions are used within a web server environment.

https://www.php.net/manual/en/intro.pcntl.php

How can pcntl_fork be supported?

The pcntl extension uses fork() internally:

https://github.com/php/php-src/blob/f35e1d517fab691db008f1889879533ffe02d7f3/ext/pcntl/pcntl.c#L179-L194

However, Emscripten does not support fork():

The Emscripten implementation does also not support multiprocessing via fork() and join().
https://emscripten.org/docs/porting/pthreads.html

The forked processes are supposed to start executing on the next statement after the fork() call. This is impossible in the current features of JavaScript (unless we use something like emterpreter to emulate code execution), since we are not able to duplicate the callstack of the parent to the forked children so that they'd be executing at the same exact functions and local values on their stack.
emscripten-core/emscripten#4182

However, Emscripten does support pthreads.

Therefore, perhaps there is a way to shim fork() in some way?

child_process.fork()

In Node.js, we have access to a fork() function. However, despite a similar name, it has different semantics than the C fork() function in that it runs an entirely new JS module instead of cloning the currently-running one at the point where fork() is called.

Pthreads

One angle for shimming could be pthread_create(). Here are the differences according to this SO answer:

fork()

  • Purpose is to create a new process, which becomes the child process of the caller
  • Both processes will execute the next instruction following the fork() system call
  • Two identical copies of the computer's address space,code, and stack are created one for parent and child.

pthread_create()

  • Purpose is to create a new thread in the program which is given the same process of the caller
  • Threads within the same process can communicate using shared memory. (Be careful!)
  • The second thread will share data,open files, signal handlers and signal dispositions, current working directory, user and group ID's. The new thread will get its own stack, thread ID, and registers though.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions