The customer has hundreds of Emperor-managed PSGI applications built upon the same code base.
Those apps start pretty slow, so they could highly benefit from fork() copy on write.
The Emperor calls fork()/clone() and execve() for each vassal so they spawn with a clean setup. Execve functions clear the whole memory map of the process so inheriting the copy of an application is impossible.
The idea:
The PSGI plugin exposes a new option: --early-psgi
This option of type "IMMEDIATE" (it means the options is executed soon after parsing) initialize a perl interpreter and load the specified app in it exposing its entry point address in a global area.
Soon after the initialization, (and thanks to the --fork-socket option) the uWSGI process binds to a UNIX address looply waiting for connections.
Each connection will trigger a double fork() and will pass up to 3 file descriptors:
the Emperor pipe (for controlling the vassal)
the Emperor config pipe (where config blobs are passed, if needed)
the Emperor on_demand file descriptor (if needed)
In addition to the file descriptors a uwsgi-serialized array is passed with the vassal command line options. Those options override the old ones, and the config parser is run again, triggering the spawn of a fully capable instance.
The Emperor side:
instead of calling fork() for each vassal, a connection to the fork server is made, passing the vassal's file descriptors. The Emperor is initialized with prctl(PR_SET_CHILD_SUBREAPER, 1) so every sub-children without a parent will be reparented to the Emperor (this explains the need of double-fork in the fork-server).
Now the Emperor can wait() for the sub-children, and can pass messages to the vassal file descriptors.
Introduction:
The customer has hundreds of Emperor-managed PSGI applications built upon the same code base.
Those apps start pretty slow, so they could highly benefit from fork() copy on write.
The Emperor calls fork()/clone() and execve() for each vassal so they spawn with a clean setup. Execve functions clear the whole memory map of the process so inheriting the copy of an application is impossible.
The idea:
The PSGI plugin exposes a new option: --early-psgi
This option of type "IMMEDIATE" (it means the options is executed soon after parsing) initialize a perl interpreter and load the specified app in it exposing its entry point address in a global area.
Soon after the initialization, (and thanks to the --fork-socket option) the uWSGI process binds to a UNIX address looply waiting for connections.
Each connection will trigger a double fork() and will pass up to 3 file descriptors:
In addition to the file descriptors a uwsgi-serialized array is passed with the vassal command line options. Those options override the old ones, and the config parser is run again, triggering the spawn of a fully capable instance.
The Emperor side:
instead of calling fork() for each vassal, a connection to the fork server is made, passing the vassal's file descriptors. The Emperor is initialized with prctl(PR_SET_CHILD_SUBREAPER, 1) so every sub-children without a parent will be reparented to the Emperor (this explains the need of double-fork in the fork-server).
Now the Emperor can wait() for the sub-children, and can pass messages to the vassal file descriptors.