Created
July 3, 2014 11:14
-
-
Save dermesser/e2f9b66457ae19ebd116 to your computer and use it in GitHub Desktop.
In case anyone wants to see a multi-threaded FastCGI application written with the fcgiapp library.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# include <stdlib.h> | |
# include <stdio.h> | |
# include <sys/stat.h> | |
# include <pthread.h> | |
# include <fcgiapp.h> | |
const char* const sockpath = "/tmp/fcgicpp.sock"; | |
void* start_fcgi_worker(void* arg); | |
struct FCGI_Info | |
{ | |
int fcgi_fd; | |
}; | |
int main(void) | |
{ | |
int fcgifd = FCGX_OpenSocket(sockpath,128); | |
chmod(sockpath,0777); | |
if ( 0 > fcgifd ) | |
{ | |
printf("Error opening socket\n"); | |
exit(1); | |
} | |
/* | |
if ( FCGX_IsCGI() ) | |
{ | |
printf("Please run this process as FastCGI process.\n"); | |
exit(1); | |
} | |
*/ | |
const unsigned int n_threads = 4; | |
pthread_t threads[n_threads]; | |
struct FCGI_Info info; | |
info.fcgi_fd = fcgifd; | |
for ( unsigned int i = 0; i < n_threads; i++ ) | |
{ | |
pthread_create(&threads[i],NULL,start_fcgi_worker,(void*)&info); | |
} | |
// Wait indefinitely | |
for ( unsigned int i = 0; i < n_threads; i++ ) | |
{ | |
pthread_join(threads[i],NULL); | |
} | |
return 0; | |
} | |
void* start_fcgi_worker(void* arg) | |
{ | |
struct FCGI_Info* info = (struct FCGI_Info*)arg; | |
FCGX_Init(); | |
FCGX_Request request; | |
FCGX_InitRequest(&request,info->fcgi_fd,0); | |
while ( 1 ) | |
{ | |
FCGX_Accept_r(&request); | |
FCGX_PutStr("Content-type: text/plain\r\n\r\n",28,request.out); | |
FCGX_PutStr("Hey!\n",5,request.out); | |
FCGX_Finish_r(&request); | |
} | |
} |
Well done mate (2 years after)
Did you try fastcgi using tcp ports instead of Unix sockets?
What hardware have you used and how did you run these tests? I want to do some tests on my FCGI app...
Cheers
This is beautiful.
You may optimize (or improve/analyze) this code by doing the following:
- Move away FCGX_Init() from worker to main thread
- Remove whole struct FCGI_Info, because it contains only fd, which is used globally and it value is the same for all threads. Declare fd in global scope
- There is a memory leak in fastcgi library itself. In order to fix it you may need to
#include <fcgios.h>
and executeOS_LibShutdown();
at end of main thread - Currently in this example there is no way to gracefully shut down threads because they are not receiving signals. The proper way to do that is to make syscalls with EINTR enabled and send to each thread signal(s)
- For some reason in this "official" example https://github.com/FastCGI-Archives/fcgi2/blob/master/examples/threaded.c
FCGX_Accept_r(&request)
is evaluated with mutex-es protection. Have no idea if you or me should do the same.
Locking around calls to FCGX_Accept_r seem unnecessary. The header file says "(multi-thread safe)".
Thank you all for your comments! They are really helpful :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This server can handle up to 20k requests/second on an nginx installation that itself is capable of serving ~50k static file requests per second.