Skip to content

Instantly share code, notes, and snippets.

@binki
Created May 27, 2017 16:45
Show Gist options
  • Save binki/62bcd4408ba6bef71e01a96abbf01a71 to your computer and use it in GitHub Desktop.
Save binki/62bcd4408ba6bef71e01a96abbf01a71 to your computer and use it in GitHub Desktop.
Convention for launching SCGI applications and managing lifetimes

Status

Incomplete. I just posted to save my progress, probably completely wrong still…

Introduction

CGI (Common Gateway Interface) has been around for a long time and is considered a standard for server-side dynamic content generation. CGI provides a mapping from URI to a script stored on a filesystem and a protocol for activating the script, sending the client’s request, and returning the script’s response to the client. CGI communicates headers and request information to the script by setting well known environment variables and executes it to activate it. This results in different types of overhead: concurrent requests require multiple processes and each request requires a fork(), exec(), and quite likely a script interpreter which may need to consume many resources before being able to respond to the request. The common solution to this overhead is to run a persistent server which handles multiple requests instead of launching a script for each requests.

FastCGI, especially mod_fcgid, enables a script to act as both a traditional CGI script and upgrade to a persistent process mode. FasctCGI has a complex protocol supporting one process with multiplexed requests but describes requests using the same well-known environment variables as CGI, allowing scripts to be written once and while supporting both CGI and FastCGI. However, the most common httpd implementations of FastCGI do not support its multiplexing protocol, so a high request concurrency requires many processes to be spawned and long-running requests are impractical. SCGI provides a simple alternative to FastCGI which, like FastCGI, reuses the meanings of environment variables CGI but, by using a new connection for each request, gains concurrency support from all httpds because they don’t have to implement multiplexing to use it.

This specification is meant to describe a protocol whereby a CGI script and httpd module may upgrade from CGI to either FastCGI or SCGI. This specification suggests a convention whereby an httpd or script may implement all three protocols, just two, or just one.

Necessary Tasks

  1. Convention to automatically launch SCGI processes.
  2. Optional prelaunching to avoid warmup delay for the first request.
  3. Enable launched application to detect it is in an SCGI environment.
  4. Communicate SCGI parameters back to httpd.
  5. Manage child’s lifetime safely to avoid orphanage.

Protocol

Script Discovery

FastCGI provides no mechanism for the httpd to determine if a launched script supports FastCGI or not. Thus, the person configuring the httpd must know that CGI scripts support FastCGI before enabling it for them. This specification provides a recommendation for resolving that ambiguity.

httpds have a mechanism for resolving URIs to on-disk paths such as rewrites, aliases, and directory indexes. The ending of the resolved path shall have these meanings:

  1. .cgi: the file should implement the CGI interface. If the resolved path is an executable file ending with .cgi, that file should implement the CGI interface. If the resolved path is a If the resolved path is an executable file ending with .scgi, that file should implement at least the SCGI autolaunch interface.

Script Launching

An SCGI-enabled server should perform these steps or their platform-specific equivalents when launching a script which it wishes to use SCGI with. This set of steps is meant to be compatible with FastCGI on unix platforms and CGI on all platforms.

  1. fork()
  2. Set up a pipe for writing input.
  3. Set up a pipe for reading output.
  4. Optionally set up a pipe for reading errors.
  5. exec() the script with SCGI=1 in its environment, standard input set to the pipe set for writing, standard output set to the pipe for reading, and optionally standard error set to the pipe for reading errors. If the server supports CGI, the script’s filename ends in .cgi, and the script is being launched in response to a request, CGI environment variables should be set too.
  6. If the server supports CGI and the request type would require writing to the CGI program’s standard input, the server should

Script Execution

An SCGI-enabled script should first check if there is an environment variable SCGI=1. If this variable is found with this value, it should perform these steps:

  1. Remove SCGI from its environment (to avoid spawning subprocesses with SCGI=1).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment