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 hidden or 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); | |
} | |
} |
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 is beautiful.