Fix a bug that caused an assert to pop when an async file descriptor
[catagits/fcgi2.git] / libfcgi / os_unix.c
CommitLineData
aadcc3c8 1/*
0198fd3c 2 * os_unix.c --
3 *
4 * Description of file.
5 *
6 *
7 * Copyright (c) 1995 Open Market, Inc.
8 * All rights reserved.
9 *
10 * This file contains proprietary and confidential information and
aadcc3c8 11 * remains the unpublished property of Open Market, Inc. Use,
12 * disclosure, or reproduction is prohibited except as permitted by
13 * express written license agreement with Open Market, Inc.
0198fd3c 14 *
15 * Bill Snapper
16 * snapper@openmarket.com
17 */
18
19#ifndef lint
a34d549f 20static const char rcsid[] = "$Id: os_unix.c,v 1.36 2002/02/19 00:45:55 robs Exp $";
0198fd3c 21#endif /* not lint */
22
6ad90ad2 23#include "fcgi_config.h"
0198fd3c 24
27064097 25#include <sys/types.h>
26
8db9dd8f 27#ifdef HAVE_NETINET_IN_H
28#include <netinet/in.h>
29#endif
30
6ad90ad2 31#include <arpa/inet.h>
0198fd3c 32#include <assert.h>
0198fd3c 33#include <errno.h>
6ad90ad2 34#include <fcntl.h> /* for fcntl */
0198fd3c 35#include <math.h>
6ad90ad2 36#include <memory.h> /* for memchr() */
37#include <netinet/tcp.h>
38#include <stdarg.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <sys/time.h>
0198fd3c 43#include <sys/un.h>
d0686b0d 44#include <signal.h>
6ad90ad2 45
0198fd3c 46#ifdef HAVE_NETDB_H
47#include <netdb.h>
48#endif
0198fd3c 49
6ad90ad2 50#ifdef HAVE_SYS_SOCKET_H
51#include <sys/socket.h> /* for getpeername */
52#endif
53
54#ifdef HAVE_UNISTD_H
55#include <unistd.h>
56#endif
57
58#include "fastcgi.h"
6ad90ad2 59#include "fcgimisc.h"
0198fd3c 60#include "fcgios.h"
61
03f366ba 62#ifndef INADDR_NONE
63#define INADDR_NONE ((unsigned long) -1)
64#endif
65
0198fd3c 66/*
67 * This structure holds an entry for each oustanding async I/O operation.
68 */
69typedef struct {
70 OS_AsyncProc procPtr; /* callout completion procedure */
71 ClientData clientData; /* caller private data */
72 int fd;
73 int len;
74 int offset;
75 void *buf;
76 int inUse;
77} AioInfo;
78
79/*
80 * Entries in the async I/O table are allocated 2 per file descriptor.
81 *
82 * Read Entry Index = fd * 2
83 * Write Entry Index = (fd * 2) + 1
84 */
85#define AIO_RD_IX(fd) (fd * 2)
86#define AIO_WR_IX(fd) ((fd * 2) + 1)
87
2b391aca 88static int asyncIoInUse = FALSE;
0198fd3c 89static int asyncIoTableSize = 16;
90static AioInfo *asyncIoTable = NULL;
0198fd3c 91
0198fd3c 92static int libInitialized = FALSE;
93
94static fd_set readFdSet;
95static fd_set writeFdSet;
96
97static fd_set readFdSetPost;
98static int numRdPosted = 0;
99static fd_set writeFdSetPost;
100static int numWrPosted = 0;
101static int volatile maxFd = -1;
102
d0686b0d 103static int shutdownPending = FALSE;
104static int shutdownNow = FALSE;
105
d0686b0d 106void OS_ShutdownPending()
107{
108 shutdownPending = TRUE;
109}
110
994e1bb8 111static void OS_Sigusr1Handler(int signo)
d0686b0d 112{
113 OS_ShutdownPending();
114}
115
994e1bb8 116static void OS_SigpipeHandler(int signo)
d0686b0d 117{
118 ;
119}
120
121static void installSignalHandler(int signo, const struct sigaction * act, int force)
122{
123 struct sigaction sa;
124
125 sigaction(signo, NULL, &sa);
126
127 if (force || sa.sa_handler == SIG_DFL)
128 {
129 sigaction(signo, act, NULL);
130 }
131}
132
994e1bb8 133static void OS_InstallSignalHandlers(int force)
d0686b0d 134{
135 struct sigaction sa;
136
137 sigemptyset(&sa.sa_mask);
138 sa.sa_flags = 0;
139
140 sa.sa_handler = OS_SigpipeHandler;
141 installSignalHandler(SIGPIPE, &sa, force);
142
143 sa.sa_handler = OS_Sigusr1Handler;
144 installSignalHandler(SIGUSR1, &sa, force);
d0686b0d 145}
146
0198fd3c 147/*
148 *--------------------------------------------------------------
149 *
150 * OS_LibInit --
151 *
152 * Set up the OS library for use.
153 *
154 * NOTE: This function is really only needed for application
155 * asynchronous I/O. It will most likely change in the
156 * future to setup the multi-threaded environment.
157 *
158 * Results:
159 * Returns 0 if success, -1 if not.
160 *
161 * Side effects:
162 * Async I/O table allocated and initialized.
163 *
164 *--------------------------------------------------------------
165 */
166int OS_LibInit(int stdioFds[3])
167{
168 if(libInitialized)
169 return 0;
aadcc3c8 170
171 asyncIoTable = (AioInfo *)malloc(asyncIoTableSize * sizeof(AioInfo));
0198fd3c 172 if(asyncIoTable == NULL) {
173 errno = ENOMEM;
174 return -1;
175 }
176 memset((char *) asyncIoTable, 0,
177 asyncIoTableSize * sizeof(AioInfo));
178
179 FD_ZERO(&readFdSet);
180 FD_ZERO(&writeFdSet);
181 FD_ZERO(&readFdSetPost);
182 FD_ZERO(&writeFdSetPost);
d0686b0d 183
184 OS_InstallSignalHandlers(FALSE);
185
0198fd3c 186 libInitialized = TRUE;
d0686b0d 187
0198fd3c 188 return 0;
189}
190
0198fd3c 191/*
192 *--------------------------------------------------------------
193 *
194 * OS_LibShutdown --
195 *
196 * Shutdown the OS library.
197 *
198 * Results:
199 * None.
200 *
201 * Side effects:
202 * Memory freed, fds closed.
203 *
204 *--------------------------------------------------------------
205 */
206void OS_LibShutdown()
207{
208 if(!libInitialized)
209 return;
aadcc3c8 210
0198fd3c 211 free(asyncIoTable);
212 asyncIoTable = NULL;
213 libInitialized = FALSE;
214 return;
215}
216
0198fd3c 217/*
218 *----------------------------------------------------------------------
219 *
220 * OS_BuildSockAddrUn --
221 *
222 * Using the pathname bindPath, fill in the sockaddr_un structure
223 * *servAddrPtr and the length of this structure *servAddrLen.
224 *
225 * The format of the sockaddr_un structure changed incompatibly in
226 * 4.3BSD Reno. Digital UNIX supports both formats, other systems
227 * support one or the other.
228 *
229 * Results:
230 * 0 for normal return, -1 for failure (bindPath too long).
231 *
232 *----------------------------------------------------------------------
233 */
234
0b7c9662 235static int OS_BuildSockAddrUn(const char *bindPath,
0198fd3c 236 struct sockaddr_un *servAddrPtr,
237 int *servAddrLen)
238{
239 int bindPathLen = strlen(bindPath);
240
241#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
242 if(bindPathLen >= sizeof(servAddrPtr->sun_path)) {
243 return -1;
244 }
245#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
246 if(bindPathLen > sizeof(servAddrPtr->sun_path)) {
247 return -1;
248 }
249#endif
250 memset((char *) servAddrPtr, 0, sizeof(*servAddrPtr));
251 servAddrPtr->sun_family = AF_UNIX;
252 memcpy(servAddrPtr->sun_path, bindPath, bindPathLen);
253#ifdef HAVE_SOCKADDR_UN_SUN_LEN /* 4.3BSD Reno and later: BSDI, DEC */
254 *servAddrLen = sizeof(servAddrPtr->sun_len)
255 + sizeof(servAddrPtr->sun_family)
256 + bindPathLen + 1;
257 servAddrPtr->sun_len = *servAddrLen;
258#else /* 4.3 BSD Tahoe: Solaris, HPUX, DEC, ... */
259 *servAddrLen = sizeof(servAddrPtr->sun_family) + bindPathLen;
260#endif
261 return 0;
262}
0198fd3c 263union SockAddrUnion {
264 struct sockaddr_un unixVariant;
265 struct sockaddr_in inetVariant;
266};
267
0198fd3c 268/*
269 * OS_CreateLocalIpcFd --
270 *
271 * This procedure is responsible for creating the listener socket
272 * on Unix for local process communication. It will create a
273 * domain socket or a TCP/IP socket bound to "localhost" and return
274 * a file descriptor to it to the caller.
275 *
276 * Results:
277 * Listener socket created. This call returns either a valid
278 * file descriptor or -1 on error.
279 *
280 * Side effects:
281 * None.
282 *
283 *----------------------------------------------------------------------
284 */
0b7c9662 285int OS_CreateLocalIpcFd(const char *bindPath, int backlog)
0198fd3c 286{
287 int listenSock, servLen;
630ce256 288 union SockAddrUnion sa;
0198fd3c 289 int tcp = FALSE;
9f2857f4 290 unsigned long tcp_ia = 0;
0198fd3c 291 char *tp;
9f2857f4 292 short port = 0;
0198fd3c 293 char host[MAXPATHLEN];
294
295 strcpy(host, bindPath);
296 if((tp = strchr(host, ':')) != 0) {
297 *tp++ = 0;
298 if((port = atoi(tp)) == 0) {
299 *--tp = ':';
300 } else {
301 tcp = TRUE;
302 }
303 }
03f366ba 304 if(tcp) {
305 if (!*host || !strcmp(host,"*")) {
306 tcp_ia = htonl(INADDR_ANY);
307 } else {
308 tcp_ia = inet_addr(host);
309 if (tcp_ia == INADDR_NONE) {
310 struct hostent * hep;
311 hep = gethostbyname(host);
312 if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
313 fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host);
314 exit(1);
315 }
316 if (hep->h_addr_list[1]) {
317 fprintf(stderr, "Host %s has multiple addresses ---\n", host);
318 fprintf(stderr, "you must choose one explicitly!!!\n");
319 exit(1);
320 }
321 tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr;
322 }
323 }
0198fd3c 324 }
325
326 if(tcp) {
327 listenSock = socket(AF_INET, SOCK_STREAM, 0);
328 if(listenSock >= 0) {
329 int flag = 1;
330 if(setsockopt(listenSock, SOL_SOCKET, SO_REUSEADDR,
331 (char *) &flag, sizeof(flag)) < 0) {
332 fprintf(stderr, "Can't set SO_REUSEADDR.\n");
333 exit(1001);
334 }
335 }
336 } else {
337 listenSock = socket(AF_UNIX, SOCK_STREAM, 0);
338 }
339 if(listenSock < 0) {
340 return -1;
341 }
342
343 /*
344 * Bind the listening socket.
345 */
346 if(tcp) {
347 memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant));
348 sa.inetVariant.sin_family = AF_INET;
03f366ba 349 sa.inetVariant.sin_addr.s_addr = tcp_ia;
0198fd3c 350 sa.inetVariant.sin_port = htons(port);
351 servLen = sizeof(sa.inetVariant);
352 } else {
353 unlink(bindPath);
354 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
355 fprintf(stderr, "Listening socket's path name is too long.\n");
356 exit(1000);
357 }
358 }
359 if(bind(listenSock, (struct sockaddr *) &sa.unixVariant, servLen) < 0
0b7c9662 360 || listen(listenSock, backlog) < 0) {
0198fd3c 361 perror("bind/listen");
362 exit(errno);
363 }
364
365 return listenSock;
366}
367
0198fd3c 368/*
369 *----------------------------------------------------------------------
370 *
371 * OS_FcgiConnect --
372 *
373 * Create the socket and connect to the remote application if
374 * possible.
375 *
376 * This was lifted from the cgi-fcgi application and was abstracted
377 * out because Windows NT does not have a domain socket and must
378 * use a named pipe which has a different API altogether.
379 *
380 * Results:
381 * -1 if fail or a valid file descriptor if connection succeeds.
382 *
383 * Side effects:
384 * Remote connection established.
385 *
386 *----------------------------------------------------------------------
387 */
388int OS_FcgiConnect(char *bindPath)
389{
390 union SockAddrUnion sa;
391 int servLen, resultSock;
392 int connectStatus;
393 char *tp;
394 char host[MAXPATHLEN];
df986e9d 395 short port = 0;
0198fd3c 396 int tcp = FALSE;
397
398 strcpy(host, bindPath);
399 if((tp = strchr(host, ':')) != 0) {
400 *tp++ = 0;
401 if((port = atoi(tp)) == 0) {
402 *--tp = ':';
403 } else {
404 tcp = TRUE;
405 }
406 }
407 if(tcp == TRUE) {
408 struct hostent *hp;
409 if((hp = gethostbyname((*host ? host : "localhost"))) == NULL) {
410 fprintf(stderr, "Unknown host: %s\n", bindPath);
411 exit(1000);
412 }
413 sa.inetVariant.sin_family = AF_INET;
203fd55e 414 memcpy(&sa.inetVariant.sin_addr, hp->h_addr, hp->h_length);
0198fd3c 415 sa.inetVariant.sin_port = htons(port);
416 servLen = sizeof(sa.inetVariant);
417 resultSock = socket(AF_INET, SOCK_STREAM, 0);
418 } else {
419 if(OS_BuildSockAddrUn(bindPath, &sa.unixVariant, &servLen)) {
420 fprintf(stderr, "Listening socket's path name is too long.\n");
421 exit(1000);
422 }
423 resultSock = socket(AF_UNIX, SOCK_STREAM, 0);
424 }
425
6f902b14 426 ASSERT(resultSock >= 0);
0198fd3c 427 connectStatus = connect(resultSock, (struct sockaddr *) &sa.unixVariant,
428 servLen);
429 if(connectStatus >= 0) {
430 return resultSock;
431 } else {
432 /*
433 * Most likely (errno == ENOENT || errno == ECONNREFUSED)
434 * and no FCGI application server is running.
435 */
436 close(resultSock);
437 return -1;
438 }
439}
aadcc3c8 440
0198fd3c 441/*
442 *--------------------------------------------------------------
443 *
444 * OS_Read --
445 *
446 * Pass through to the unix read function.
447 *
448 * Results:
449 * Returns number of byes read, 0, or -1 failure: errno
450 * contains actual error.
451 *
452 * Side effects:
453 * None.
454 *
455 *--------------------------------------------------------------
456 */
457int OS_Read(int fd, char * buf, size_t len)
458{
d0686b0d 459 if (shutdownNow) return -1;
0198fd3c 460 return(read(fd, buf, len));
461}
62e100c7 462
0198fd3c 463/*
464 *--------------------------------------------------------------
465 *
466 * OS_Write --
467 *
468 * Pass through to unix write function.
469 *
470 * Results:
471 * Returns number of byes read, 0, or -1 failure: errno
472 * contains actual error.
473 *
474 * Side effects:
475 * none.
476 *
477 *--------------------------------------------------------------
478 */
479int OS_Write(int fd, char * buf, size_t len)
480{
d0686b0d 481 if (shutdownNow) return -1;
0198fd3c 482 return(write(fd, buf, len));
483}
484
0198fd3c 485/*
486 *----------------------------------------------------------------------
487 *
488 * OS_SpawnChild --
489 *
490 * Spawns a new FastCGI listener process.
491 *
492 * Results:
493 * 0 if success, -1 if error.
494 *
495 * Side effects:
496 * Child process spawned.
497 *
498 *----------------------------------------------------------------------
499 */
500int OS_SpawnChild(char *appPath, int listenFd)
501{
502 int forkResult;
503
504 forkResult = fork();
505 if(forkResult < 0) {
506 exit(errno);
507 }
508
509 if(forkResult == 0) {
510 /*
511 * Close STDIN unconditionally. It's used by the parent
512 * process for CGI communication. The FastCGI applciation
513 * will be replacing this with the FastCGI listenFd IF
514 * STDIN_FILENO is the same as FCGI_LISTENSOCK_FILENO
515 * (which it is on Unix). Regardless, STDIN, STDOUT, and
516 * STDERR will be closed as the FastCGI process uses a
517 * multiplexed socket in their place.
518 */
519 close(STDIN_FILENO);
520
521 /*
522 * If the listenFd is already the value of FCGI_LISTENSOCK_FILENO
523 * we're set. If not, change it so the child knows where to
524 * get the listen socket from.
525 */
526 if(listenFd != FCGI_LISTENSOCK_FILENO) {
527 dup2(listenFd, FCGI_LISTENSOCK_FILENO);
528 close(listenFd);
529 }
530
531 close(STDOUT_FILENO);
532 close(STDERR_FILENO);
533
534 /*
535 * We're a child. Exec the application.
536 *
537 * XXX: entire environment passes through
538 */
539 execl(appPath, appPath, NULL);
540 /*
541 * XXX: Can't do this as we've already closed STDERR!!!
542 *
543 * perror("exec");
544 */
545 exit(errno);
546 }
547 return 0;
548}
549
0198fd3c 550/*
551 *--------------------------------------------------------------
552 *
553 * OS_AsyncReadStdin --
554 *
555 * This initiates an asynchronous read on the standard
556 * input handle.
557 *
558 * The abstraction is necessary because Windows NT does not
559 * have a clean way of "select"ing a file descriptor for
560 * I/O.
561 *
562 * Results:
563 * -1 if error, 0 otherwise.
564 *
565 * Side effects:
566 * Asynchronous bit is set in the readfd variable and
567 * request is enqueued.
568 *
569 *--------------------------------------------------------------
570 */
aadcc3c8 571int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr,
0198fd3c 572 ClientData clientData)
573{
574 int index = AIO_RD_IX(STDIN_FILENO);
575
2b391aca 576 asyncIoInUse = TRUE;
0198fd3c 577 ASSERT(asyncIoTable[index].inUse == 0);
578 asyncIoTable[index].procPtr = procPtr;
579 asyncIoTable[index].clientData = clientData;
580 asyncIoTable[index].fd = STDIN_FILENO;
581 asyncIoTable[index].len = len;
582 asyncIoTable[index].offset = 0;
583 asyncIoTable[index].buf = buf;
584 asyncIoTable[index].inUse = 1;
585 FD_SET(STDIN_FILENO, &readFdSet);
586 if(STDIN_FILENO > maxFd)
587 maxFd = STDIN_FILENO;
588 return 0;
589}
590
591static void GrowAsyncTable(void)
592{
593 int oldTableSize = asyncIoTableSize;
aadcc3c8 594
0198fd3c 595 asyncIoTableSize = asyncIoTableSize * 2;
aadcc3c8 596 asyncIoTable = (AioInfo *)realloc(asyncIoTable, asyncIoTableSize * sizeof(AioInfo));
0198fd3c 597 if(asyncIoTable == NULL) {
598 errno = ENOMEM;
599 exit(errno);
600 }
601 memset((char *) &asyncIoTable[oldTableSize], 0,
602 oldTableSize * sizeof(AioInfo));
603
604}
605
0198fd3c 606/*
607 *--------------------------------------------------------------
608 *
609 * OS_AsyncRead --
610 *
611 * This initiates an asynchronous read on the file
612 * handle which may be a socket or named pipe.
613 *
614 * We also must save the ProcPtr and ClientData, so later
615 * when the io completes, we know who to call.
616 *
617 * We don't look at any results here (the ReadFile may
618 * return data if it is cached) but do all completion
619 * processing in OS_Select when we get the io completion
620 * port done notifications. Then we call the callback.
621 *
622 * Results:
623 * -1 if error, 0 otherwise.
624 *
625 * Side effects:
626 * Asynchronous I/O operation is queued for completion.
627 *
628 *--------------------------------------------------------------
629 */
630int OS_AsyncRead(int fd, int offset, void *buf, int len,
631 OS_AsyncProc procPtr, ClientData clientData)
632{
633 int index = AIO_RD_IX(fd);
aadcc3c8 634
0198fd3c 635 ASSERT(asyncIoTable != NULL);
2b391aca 636 asyncIoInUse = TRUE;
0198fd3c 637
638 if(fd > maxFd)
639 maxFd = fd;
640
a34d549f 641 while (index >= asyncIoTableSize) {
0198fd3c 642 GrowAsyncTable();
643 }
644
645 ASSERT(asyncIoTable[index].inUse == 0);
646 asyncIoTable[index].procPtr = procPtr;
647 asyncIoTable[index].clientData = clientData;
648 asyncIoTable[index].fd = fd;
649 asyncIoTable[index].len = len;
650 asyncIoTable[index].offset = offset;
651 asyncIoTable[index].buf = buf;
652 asyncIoTable[index].inUse = 1;
653 FD_SET(fd, &readFdSet);
654 return 0;
655}
62e100c7 656
0198fd3c 657/*
658 *--------------------------------------------------------------
659 *
660 * OS_AsyncWrite --
661 *
662 * This initiates an asynchronous write on the "fake" file
663 * descriptor (which may be a file, socket, or named pipe).
664 * We also must save the ProcPtr and ClientData, so later
665 * when the io completes, we know who to call.
666 *
667 * We don't look at any results here (the WriteFile generally
668 * completes immediately) but do all completion processing
669 * in OS_DoIo when we get the io completion port done
670 * notifications. Then we call the callback.
671 *
672 * Results:
673 * -1 if error, 0 otherwise.
674 *
675 * Side effects:
676 * Asynchronous I/O operation is queued for completion.
677 *
678 *--------------------------------------------------------------
679 */
aadcc3c8 680int OS_AsyncWrite(int fd, int offset, void *buf, int len,
0198fd3c 681 OS_AsyncProc procPtr, ClientData clientData)
682{
683 int index = AIO_WR_IX(fd);
684
2b391aca 685 asyncIoInUse = TRUE;
686
0198fd3c 687 if(fd > maxFd)
688 maxFd = fd;
689
a34d549f 690 while (index >= asyncIoTableSize) {
0198fd3c 691 GrowAsyncTable();
692 }
693
694 ASSERT(asyncIoTable[index].inUse == 0);
695 asyncIoTable[index].procPtr = procPtr;
696 asyncIoTable[index].clientData = clientData;
697 asyncIoTable[index].fd = fd;
698 asyncIoTable[index].len = len;
699 asyncIoTable[index].offset = offset;
700 asyncIoTable[index].buf = buf;
701 asyncIoTable[index].inUse = 1;
702 FD_SET(fd, &writeFdSet);
703 return 0;
704}
62e100c7 705
0198fd3c 706/*
707 *--------------------------------------------------------------
708 *
709 * OS_Close --
710 *
711 * Closes the descriptor. This is a pass through to the
712 * Unix close.
713 *
714 * Results:
715 * 0 for success, -1 on failure
716 *
717 * Side effects:
718 * None.
719 *
720 *--------------------------------------------------------------
721 */
722int OS_Close(int fd)
723{
8462b1ec 724 if (fd == -1)
725 return 0;
726
c92b39ad 727 if (asyncIoInUse) {
2b391aca 728 int index = AIO_RD_IX(fd);
aadcc3c8 729
2b391aca 730 FD_CLR(fd, &readFdSet);
731 FD_CLR(fd, &readFdSetPost);
732 if (asyncIoTable[index].inUse != 0) {
733 asyncIoTable[index].inUse = 0;
734 }
735
736 FD_CLR(fd, &writeFdSet);
737 FD_CLR(fd, &writeFdSetPost);
738 index = AIO_WR_IX(fd);
739 if (asyncIoTable[index].inUse != 0) {
740 asyncIoTable[index].inUse = 0;
741 }
aadcc3c8 742
2b391aca 743 if (maxFd == fd) {
744 maxFd--;
745 }
0198fd3c 746 }
0198fd3c 747 return close(fd);
748}
62e100c7 749
0198fd3c 750/*
751 *--------------------------------------------------------------
752 *
753 * OS_CloseRead --
754 *
755 * Cancel outstanding asynchronous reads and prevent subsequent
756 * reads from completing.
757 *
758 * Results:
759 * Socket or file is shutdown. Return values mimic Unix shutdown:
760 * 0 success, -1 failure
761 *
762 *--------------------------------------------------------------
763 */
764int OS_CloseRead(int fd)
765{
766 if(asyncIoTable[AIO_RD_IX(fd)].inUse != 0) {
767 asyncIoTable[AIO_RD_IX(fd)].inUse = 0;
768 FD_CLR(fd, &readFdSet);
769 }
aadcc3c8 770
0198fd3c 771 return shutdown(fd, 0);
772}
773
0198fd3c 774/*
775 *--------------------------------------------------------------
776 *
777 * OS_DoIo --
778 *
779 * This function was formerly OS_Select. It's purpose is
780 * to pull I/O completion events off the queue and dispatch
781 * them to the appropriate place.
782 *
783 * Results:
784 * Returns 0.
785 *
786 * Side effects:
787 * Handlers are called.
788 *
789 *--------------------------------------------------------------
790 */
791int OS_DoIo(struct timeval *tmo)
792{
793 int fd, len, selectStatus;
794 OS_AsyncProc procPtr;
795 ClientData clientData;
796 AioInfo *aioPtr;
797 fd_set readFdSetCpy;
798 fd_set writeFdSetCpy;
799
2b391aca 800 asyncIoInUse = TRUE;
0198fd3c 801 FD_ZERO(&readFdSetCpy);
802 FD_ZERO(&writeFdSetCpy);
803
804 for(fd = 0; fd <= maxFd; fd++) {
805 if(FD_ISSET(fd, &readFdSet)) {
806 FD_SET(fd, &readFdSetCpy);
807 }
808 if(FD_ISSET(fd, &writeFdSet)) {
809 FD_SET(fd, &writeFdSetCpy);
810 }
811 }
aadcc3c8 812
0198fd3c 813 /*
814 * If there were no completed events from a prior call, see if there's
815 * any work to do.
816 */
817 if(numRdPosted == 0 && numWrPosted == 0) {
818 selectStatus = select((maxFd+1), &readFdSetCpy, &writeFdSetCpy,
819 NULL, tmo);
820 if(selectStatus < 0) {
821 exit(errno);
822 }
823
824 for(fd = 0; fd <= maxFd; fd++) {
825 /*
826 * Build up a list of completed events. We'll work off of
827 * this list as opposed to looping through the read and write
828 * fd sets since they can be affected by a callbacl routine.
829 */
830 if(FD_ISSET(fd, &readFdSetCpy)) {
831 numRdPosted++;
832 FD_SET(fd, &readFdSetPost);
833 FD_CLR(fd, &readFdSet);
834 }
835
836 if(FD_ISSET(fd, &writeFdSetCpy)) {
837 numWrPosted++;
838 FD_SET(fd, &writeFdSetPost);
839 FD_CLR(fd, &writeFdSet);
840 }
841 }
842 }
843
844 if(numRdPosted == 0 && numWrPosted == 0)
845 return 0;
aadcc3c8 846
0198fd3c 847 for(fd = 0; fd <= maxFd; fd++) {
848 /*
849 * Do reads and dispatch callback.
850 */
aadcc3c8 851 if(FD_ISSET(fd, &readFdSetPost)
0198fd3c 852 && asyncIoTable[AIO_RD_IX(fd)].inUse) {
853
854 numRdPosted--;
855 FD_CLR(fd, &readFdSetPost);
856 aioPtr = &asyncIoTable[AIO_RD_IX(fd)];
aadcc3c8 857
0198fd3c 858 len = read(aioPtr->fd, aioPtr->buf, aioPtr->len);
859
860 procPtr = aioPtr->procPtr;
861 aioPtr->procPtr = NULL;
862 clientData = aioPtr->clientData;
863 aioPtr->inUse = 0;
864
865 (*procPtr)(clientData, len);
866 }
867
868 /*
869 * Do writes and dispatch callback.
870 */
871 if(FD_ISSET(fd, &writeFdSetPost) &&
872 asyncIoTable[AIO_WR_IX(fd)].inUse) {
873
874 numWrPosted--;
875 FD_CLR(fd, &writeFdSetPost);
876 aioPtr = &asyncIoTable[AIO_WR_IX(fd)];
aadcc3c8 877
0198fd3c 878 len = write(aioPtr->fd, aioPtr->buf, aioPtr->len);
879
880 procPtr = aioPtr->procPtr;
881 aioPtr->procPtr = NULL;
882 clientData = aioPtr->clientData;
883 aioPtr->inUse = 0;
884 (*procPtr)(clientData, len);
885 }
886 }
887 return 0;
888}
889
226e4c76 890/*
891 * Not all systems have strdup().
892 * @@@ autoconf should determine whether or not this is needed, but for now..
893 */
37605d3c 894static char * str_dup(const char * str)
226e4c76 895{
896 char * sdup = (char *) malloc(strlen(str) + 1);
897
898 if (sdup)
899 strcpy(sdup, str);
900
901 return sdup;
902}
903
0198fd3c 904/*
905 *----------------------------------------------------------------------
906 *
907 * ClientAddrOK --
908 *
909 * Checks if a client address is in a list of allowed addresses
910 *
911 * Results:
912 * TRUE if address list is empty or client address is present
913 * in the list, FALSE otherwise.
914 *
915 *----------------------------------------------------------------------
916 */
0b7c9662 917static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList)
0198fd3c 918{
919 int result = FALSE;
920 char *clientListCopy, *cur, *next;
0198fd3c 921
226e4c76 922 if (clientList == NULL || *clientList == '\0') {
0198fd3c 923 return TRUE;
924 }
925
226e4c76 926 clientListCopy = str_dup(clientList);
aadcc3c8 927
226e4c76 928 for (cur = clientListCopy; cur != NULL; cur = next) {
0198fd3c 929 next = strchr(cur, ',');
226e4c76 930 if (next != NULL) {
0198fd3c 931 *next++ = '\0';
226e4c76 932 }
933 if (inet_addr(cur) == saPtr->sin_addr.s_addr) {
0198fd3c 934 result = TRUE;
935 break;
936 }
937 }
226e4c76 938
0198fd3c 939 free(clientListCopy);
940 return result;
941}
942
0198fd3c 943/*
944 *----------------------------------------------------------------------
945 *
946 * AcquireLock --
947 *
948 * On platforms that implement concurrent calls to accept
949 * on a shared listening ipcFd, returns 0. On other platforms,
950 * acquires an exclusive lock across all processes sharing a
951 * listening ipcFd, blocking until the lock has been acquired.
952 *
953 * Results:
954 * 0 for successful call, -1 in case of system error (fatal).
955 *
956 * Side effects:
957 * This process now has the exclusive lock.
958 *
959 *----------------------------------------------------------------------
960 */
0b7c9662 961static int AcquireLock(int sock, int fail_on_intr)
0198fd3c 962{
963#ifdef USE_LOCKING
0b7c9662 964 do {
965 struct flock lock;
966 lock.l_type = F_WRLCK;
967 lock.l_start = 0;
968 lock.l_whence = SEEK_SET;
969 lock.l_len = 0;
970
971 if (fcntl(sock, F_SETLKW, &lock) != -1)
972 return 0;
98aeb41b 973 } while (errno == EINTR
974 && ! fail_on_intr
975 && ! shutdownPending);
0b7c9662 976
977 return -1;
978
979#else
0198fd3c 980 return 0;
0b7c9662 981#endif
0198fd3c 982}
62e100c7 983
0198fd3c 984/*
985 *----------------------------------------------------------------------
986 *
987 * ReleaseLock --
988 *
989 * On platforms that implement concurrent calls to accept
990 * on a shared listening ipcFd, does nothing. On other platforms,
991 * releases an exclusive lock acquired by AcquireLock.
992 *
993 * Results:
994 * 0 for successful call, -1 in case of system error (fatal).
995 *
996 * Side effects:
997 * This process no longer holds the lock.
998 *
999 *----------------------------------------------------------------------
1000 */
0b7c9662 1001static int ReleaseLock(int sock)
0198fd3c 1002{
1003#ifdef USE_LOCKING
0b7c9662 1004 do {
1005 struct flock lock;
1006 lock.l_type = F_UNLCK;
1007 lock.l_start = 0;
1008 lock.l_whence = SEEK_SET;
1009 lock.l_len = 0;
1010
1011 if (fcntl(sock, F_SETLK, &lock) != -1)
1012 return 0;
1013 } while (errno == EINTR);
0198fd3c 1014
0b7c9662 1015 return -1;
1016
1017#else
0198fd3c 1018 return 0;
0b7c9662 1019#endif
0198fd3c 1020}
1021
69f62c0e 1022/**********************************************************************
aadcc3c8 1023 * Determine if the errno resulting from a failed accept() warrants a
69f62c0e 1024 * retry or exit(). Based on Apache's http_main.c accept() handling
1025 * and Stevens' Unix Network Programming Vol 1, 2nd Ed, para. 15.6.
1026 */
1027static int is_reasonable_accept_errno (const int error)
1028{
1029 switch (error) {
1030#ifdef EPROTO
aadcc3c8 1031 /* EPROTO on certain older kernels really means ECONNABORTED, so
1032 * we need to ignore it for them. See discussion in new-httpd
1033 * archives nh.9701 search for EPROTO. Also see nh.9603, search
1034 * for EPROTO: There is potentially a bug in Solaris 2.x x<6, and
1035 * other boxes that implement tcp sockets in userland (i.e. on top of
1036 * STREAMS). On these systems, EPROTO can actually result in a fatal
1037 * loop. See PR#981 for example. It's hard to handle both uses of
69f62c0e 1038 * EPROTO. */
1039 case EPROTO:
1040#endif
1041#ifdef ECONNABORTED
1042 case ECONNABORTED:
1043#endif
1044 /* Linux generates the rest of these, other tcp stacks (i.e.
1045 * bsd) tend to hide them behind getsockopt() interfaces. They
1046 * occur when the net goes sour or the client disconnects after the
1047 * three-way handshake has been done in the kernel but before
1048 * userland has picked up the socket. */
1049#ifdef ECONNRESET
1050 case ECONNRESET:
1051#endif
1052#ifdef ETIMEDOUT
1053 case ETIMEDOUT:
1054#endif
1055#ifdef EHOSTUNREACH
1056 case EHOSTUNREACH:
1057#endif
1058#ifdef ENETUNREACH
1059 case ENETUNREACH:
1060#endif
1061 return 1;
1062
1063 default:
1064 return 0;
1065 }
1066}
1067
1068/**********************************************************************
aadcc3c8 1069 * This works around a problem on Linux 2.0.x and SCO Unixware (maybe
1070 * others?). When a connect() is made to a Unix Domain socket, but its
1071 * not accept()ed before the web server gets impatient and close()s, an
1072 * accept() results in a valid file descriptor, but no data to read.
1073 * This causes a block on the first read() - which never returns!
1074 *
1075 * Another approach to this is to write() to the socket to provoke a
1076 * SIGPIPE, but this is a pain because of the FastCGI protocol, the fact
1077 * that whatever is written has to be universally ignored by all FastCGI
1078 * web servers, and a SIGPIPE handler has to be installed which returns
1079 * (or SIGPIPE is ignored).
1080 *
1081 * READABLE_UNIX_FD_DROP_DEAD_TIMEVAL = 2,0 by default.
1082 *
1083 * Making it shorter is probably safe, but I'll leave that to you. Making
1084 * it 0,0 doesn't work reliably. The shorter you can reliably make it,
1085 * the faster your application will be able to recover (waiting 2 seconds
1086 * may _cause_ the problem when there is a very high demand). At any rate,
1087 * this is better than perma-blocking.
1088 */
69f62c0e 1089static int is_af_unix_keeper(const int fd)
1090{
1091 struct timeval tval = { READABLE_UNIX_FD_DROP_DEAD_TIMEVAL };
1092 fd_set read_fds;
1093
1094 FD_ZERO(&read_fds);
1095 FD_SET(fd, &read_fds);
aadcc3c8 1096
69f62c0e 1097 return select(fd + 1, &read_fds, NULL, NULL, &tval) >= 0 && FD_ISSET(fd, &read_fds);
1098}
1099
0198fd3c 1100/*
1101 *----------------------------------------------------------------------
1102 *
0b7c9662 1103 * OS_Accept --
0198fd3c 1104 *
1105 * Accepts a new FastCGI connection. This routine knows whether
1106 * we're dealing with TCP based sockets or NT Named Pipes for IPC.
1107 *
1108 * Results:
1109 * -1 if the operation fails, otherwise this is a valid IPC fd.
1110 *
1111 * Side effects:
1112 * New IPC connection is accepted.
1113 *
1114 *----------------------------------------------------------------------
1115 */
1dd5d7a8 1116int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs)
0198fd3c 1117{
d0686b0d 1118 int socket = -1;
69f62c0e 1119 union {
0198fd3c 1120 struct sockaddr_un un;
a3c43615 1121 struct sockaddr_in in;
0198fd3c 1122 } sa;
ed728efb 1123
0b7c9662 1124 for (;;) {
1125 if (AcquireLock(listen_sock, fail_on_intr))
1126 return -1;
a3c43615 1127
0b7c9662 1128 for (;;) {
69f62c0e 1129 do {
0b7c9662 1130#ifdef HAVE_SOCKLEN
1131 socklen_t len = sizeof(sa);
1132#else
1133 int len = sizeof(sa);
1134#endif
d0686b0d 1135 if (shutdownPending) break;
1136 /* There's a window here */
1137
0b7c9662 1138 socket = accept(listen_sock, (struct sockaddr *)&sa, &len);
d0686b0d 1139 } while (socket < 0
1140 && errno == EINTR
98aeb41b 1141 && ! fail_on_intr
1142 && ! shutdownPending);
a3c43615 1143
69f62c0e 1144 if (socket < 0) {
994e1bb8 1145 if (shutdownPending || ! is_reasonable_accept_errno(errno)) {
a3c43615 1146 int errnoSave = errno;
d0686b0d 1147
0b7c9662 1148 ReleaseLock(listen_sock);
d0686b0d 1149
994e1bb8 1150 if (! shutdownPending) {
d0686b0d 1151 errno = errnoSave;
1152 }
1153
69f62c0e 1154 return (-1);
a3c43615 1155 }
69f62c0e 1156 errno = 0;
1157 }
0b7c9662 1158 else { /* socket >= 0 */
69f62c0e 1159 int set = 1;
aadcc3c8 1160
69f62c0e 1161 if (sa.in.sin_family != AF_INET)
1162 break;
aadcc3c8 1163
69f62c0e 1164#ifdef TCP_NODELAY
1165 /* No replies to outgoing data, so disable Nagle */
1166 setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set));
aadcc3c8 1167#endif
1168
69f62c0e 1169 /* Check that the client IP address is approved */
1dd5d7a8 1170 if (ClientAddrOK(&sa.in, webServerAddrs))
69f62c0e 1171 break;
aadcc3c8 1172
69f62c0e 1173 close(socket);
0b7c9662 1174 } /* socket >= 0 */
1175 } /* for(;;) */
aadcc3c8 1176
0b7c9662 1177 if (ReleaseLock(listen_sock))
69f62c0e 1178 return (-1);
aadcc3c8 1179
69f62c0e 1180 if (sa.in.sin_family != AF_UNIX || is_af_unix_keeper(socket))
1181 break;
aadcc3c8 1182
69f62c0e 1183 close(socket);
1184 } /* while(1) - lock */
a3c43615 1185
a3c43615 1186 return (socket);
0198fd3c 1187}
62e100c7 1188
0198fd3c 1189/*
1190 *----------------------------------------------------------------------
1191 *
1192 * OS_IpcClose
1193 *
1194 * OS IPC routine to close an IPC connection.
1195 *
1196 * Results:
1197 *
1198 *
1199 * Side effects:
1200 * IPC connection is closed.
1201 *
1202 *----------------------------------------------------------------------
1203 */
1204int OS_IpcClose(int ipcFd)
1205{
1206 return OS_Close(ipcFd);
1207}
1208
0198fd3c 1209/*
1210 *----------------------------------------------------------------------
1211 *
1212 * OS_IsFcgi --
1213 *
1214 * Determines whether this process is a FastCGI process or not.
1215 *
1216 * Results:
1217 * Returns 1 if FastCGI, 0 if not.
1218 *
1219 * Side effects:
1220 * None.
1221 *
1222 *----------------------------------------------------------------------
1223 */
0b7c9662 1224int OS_IsFcgi(int sock)
0198fd3c 1225{
b22c3782 1226 union {
1227 struct sockaddr_in in;
1228 struct sockaddr_un un;
1229 } sa;
8eac3e1b 1230#ifdef HAVE_SOCKLEN
ed728efb 1231 socklen_t len = sizeof(sa);
1232#else
b22c3782 1233 int len = sizeof(sa);
ed728efb 1234#endif
0198fd3c 1235
f43b4006 1236 errno = 0;
36c03862 1237
0b7c9662 1238 if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
1239 return TRUE;
1240 }
1241 else {
1242 return FALSE;
1243 }
0198fd3c 1244}
62e100c7 1245
0198fd3c 1246/*
1247 *----------------------------------------------------------------------
1248 *
1249 * OS_SetFlags --
1250 *
1251 * Sets selected flag bits in an open file descriptor.
1252 *
1253 *----------------------------------------------------------------------
1254 */
1255void OS_SetFlags(int fd, int flags)
1256{
1257 int val;
1258 if((val = fcntl(fd, F_GETFL, 0)) < 0) {
1259 exit(errno);
1260 }
1261 val |= flags;
1262 if(fcntl(fd, F_SETFL, val) < 0) {
1263 exit(errno);
1264 }
1265}