* USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Log: wcgi.c,v $
- * Revision 1.14 1996/01/12 13:08:06 adam
+ * Revision 1.15 1996/01/26 09:02:20 adam
+ * Open of client FIFO called with O_NDELAY when reconnecting to shell
+ * in order to prevent serious lock if previous shell died without
+ * unlinking client FIFO.
+ *
+ * Revision 1.14 1996/01/12 13:08:06 adam
* CGI script passes name of lock file to the shell. The server will not close
* the response FIFO until this file becomes unlocked. This method handles
* cancel operations much better.
gw_log_session (getpid());
gw_log (GW_LOG_STAT, prog, "Europagate www cgi server");
+ /* Create fifo directory if it doesn't exist already */
sprintf(tmp, "%s/%s", FIFOROOT, FIFODIR);
if (access(tmp, R_OK|W_OK) < 0 && mkdir(tmp, 0777) < 0)
{
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "Failed to create %s", tmp);
fatal("Internal error in server.");
}
+ /* Delete server FIFO if it does exist */
sprintf(serverp, "%s/srv%d", tmp, getpid());
if (access(serverp, R_OK|W_OK) == 0)
{
else
gw_log (GW_LOG_WARN, prog, "Removed stale server fifo.");
}
+ /* Make server FIFO */
if (mkfifo(serverp, 0666 | S_IFIFO) < 0)
{
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "mkfifo(%s)", serverp);
fatal("Internal error in server.");
}
+ /* The httpd server must pass PATH_INFO */
if (!(path_info = getenv("PATH_INFO")))
{
gw_log (GW_LOG_FATAL, prog, "Must set PATH_INFO.");
fatal("Internal error in server.");
}
+ /* Create lock file that ensures the server (shell) doesn't */
+ /* terminate before we have read the whole response */
sprintf (serverf, "%s/srf%d", tmp, getpid ());
gw_log (GW_LOG_DEBUG, prog, "open w %s", serverf);
serverf_fd = open (serverf, O_WRONLY|O_CREAT|O_TRUNC, 0666);
area.l_len = 0L;
fcntl (serverf_fd, F_SETLK, &area);
}
+ /* Read first part of path_info. Either it is a numeric session id */
+ /* or it is the name of a backend shell. */
operation = ++path_info;
while (*path_info && *path_info != '/')
path_info++;
exit (1);
}
gw_log (GW_LOG_DEBUG, prog, "www.db ok");
+ /* Is operation a backend shell (new session) ? */
if ((gw_id = atoi(operation)) <= 0)
{
int r;
char gw_id_str[16];
+ /* Get new unique id */
gw_id = gw_db_seq_no (gw_db);
sprintf (gw_id_str, "%d", gw_id);
-
+
+ /* Spawn backend shell (server) */
spawn(operation, gw_id);
r = gw_db_insert (gw_db, gw_id_str, strlen(gw_id_str)+1,
operation, strlen(operation)+1);
fatal("Internal error in server");
}
gw_log (GW_LOG_DEBUG, prog, "Synchronized");
+ sprintf(clientp, "%s/clt%d", tmp, gw_id);
+ gw_log (GW_LOG_DEBUG, prog, "open w %s", clientp);
+ lineout = open (clientp, O_WRONLY);
+ }
+ else /* A session is continued */
+ {
+ sprintf(clientp, "%s/clt%d", tmp, gw_id);
+ gw_log (GW_LOG_DEBUG, prog, "open w|n %s", clientp);
+ /* Open the FIFO in O_NDELAY-mode: This prevents blocking */
+ /* even though the shell died without unlinking the FIFO */
+ /* On the other hand, if the shell is running, it will never */
+ /* close this FIFO */
+ lineout = open (clientp, O_WRONLY|O_NDELAY);
}
- sprintf(clientp, "%s/clt%d", tmp, gw_id);
- gw_log (GW_LOG_DEBUG, prog, "open w %s", clientp);
- if ((lineout = open(clientp, O_WRONLY)) < 0)
+ /* If open of clientp failed, the shell is not running, so we */
+ /* invoke it again */
+ if (lineout < 0)
{
char gw_id_str[16];
void *sprog;