Code: Select all
EnableExplicit
#MaxThread = 1
Global *FCGI_SetExitStatus
Global *FCGX_Accept_r
Global *FCGX_FClose
Global *FCGX_FPrintF
Global *FCGX_Finish_r
Global *FCGX_GetParam
Global *FCGX_Init
Global *FCGX_InitRequest
Global *FCGX_SetExitStatus
Global FCGI_Lib.i
Global Mutex.l
Global ErrFile.s
Structure S_FCGX_Request
requestId.l
role.l
*in
*out
*err
*envp
ipcFd.l
isBeginProcessed.l
keepConnection.l
appStatus.l
nWriters.l
flags.l
listen_sock.l
BetterToMuchThenToLess.l[1000]
EndStructure
; Will display an error Message
Procedure FCGI_ErrMsg(String.s)
Define File.i
File = CreateFile(#PB_Any,ErrFile)
If File <> 0
WriteStringN(File,String)
CloseFile(File)
Else
; You'll never know what happend...
EndIf
End
EndProcedure
; End Err_Msg(String.s)
; Will make sure all function are avaible
Procedure FCGI_GetFunctionSave(Lib.i,Name.s)
Define Function.i
Function = GetFunction(Lib, Name)
If Function = 0
FCGI_ErrMsg("Cannot find pointer to function " + Name)
Else
ProcedureReturn Function
EndIf
EndProcedure
; End FCGI_GetFunctionSave(Lib.i,Name.s)
; Will do some Init stuff
Procedure FCGI_Init()
; Init logging and error display
ErrFile = "err.txt"
DeleteFile(ErrFile)
FCGI_Lib = OpenLibrary(#PB_Any, "libfcgi.dll")
If FCGI_Lib = 0
FCGI_ErrMsg("Cannot open libfcgi.dll")
EndIf
*FCGI_SetExitStatus = FCGI_GetFunctionSave(FCGI_Lib, "FCGI_SetExitStatus")
*FCGX_Accept_r = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_Accept_r")
*FCGX_FClose = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_FClose")
*FCGX_FPrintF = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_FPrintF")
*FCGX_Finish_r = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_Finish_r")
*FCGX_GetParam = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_GetParam")
*FCGX_Init = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_Init")
*FCGX_InitRequest = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_InitRequest")
*FCGX_SetExitStatus = FCGI_GetFunctionSave(FCGI_Lib, "FCGX_SetExitStatus")
EndProcedure
; End FCGI_Init()
; Removes program from memory
Procedure FCGI_ReInit()
CloseLibrary(0)
End
EndProcedure
; End FCGI_ReInit()
; Print a String with Line Break
Procedure FCGI_PrintN(*out,String.s)
Define LineBreak.s = Chr(13) + Chr(10)
If Len(String) > 0
CallCFunctionFast(*FCGX_FPrintF, *out, @String)
EndIf
CallCFunctionFast(*FCGX_FPrintF, *out, @LineBreak)
EndProcedure
; End FCGI_PrintN(String.s)
; The Main Loop
Procedure FCGI_Main(Index.l)
Define Result.i, String.s, Count.i, Name.s
Define *in, *out, *err, *envp, *Param
Define QUERY_STRING.s
Define PATH_TRANSLATED.s
Define LOCAL_ADDR.s
Define ScriptTyp.i, ScriptValuei.i
Define ScriptName.s, ScriptValue.s
Define *ThreadRequest.S_FCGX_Request = AllocateMemory(SizeOf(S_FCGX_Request))
CallCFunctionFast(*FCGX_InitRequest,*ThreadRequest, 0, 0)
Repeat
LockMutex(Mutex)
Result = CallCFunctionFast(*FCGX_Accept_r,*ThreadRequest)
UnlockMutex(Mutex)
Delay(5000)
If Result => 0
Name.s = "QUERY_STRING"
*Param = CallCFunctionFast(*FCGX_GetParam,@Name,*ThreadRequest\envp)
QUERY_STRING = PeekS(*Param)
Name.s = "PATH_TRANSLATED"
*Param = CallCFunctionFast(*FCGX_GetParam,@Name,*ThreadRequest\envp)
PATH_TRANSLATED = PeekS(*Param)
Name.s = "LOCAL_ADDR"
*Param = CallCFunctionFast(*FCGX_GetParam,@Name,*ThreadRequest\envp)
LOCAL_ADDR = PeekS(*Param)
FCGI_PrintN(*ThreadRequest\out,"Content-type: text/html")
FCGI_PrintN(*ThreadRequest\out,"")
Count + 1
String.s = "Hello Thread Nr:" + Str(Index) ; Test Output
FCGI_PrintN(*ThreadRequest\out,String)
CallCFunctionFast(*FCGX_Finish_r,*ThreadRequest)
EndIf
Until Result < 0
;FCGI_Log("FCGI_Accept < 0 - End of Process: " + Str(Result))
Debug "Done"
CallCFunctionFast(*FCGX_SetExitStatus, 0)
EndProcedure
; End Main()
FCGI_Init()
Define n.i
Mutex = CreateMutex()
CallCFunctionFast(*FCGX_Init)
For n = 2 To #MaxThread
CreateThread(@FCGI_Main(),n)
Next
FCGI_Main(1)
FCGI_ReInit()

BTW:
here is the original code from http://www.fastcgi.com in c that was base for this:
Code: Select all
/*
* threaded.c -- A simple multi-threaded FastCGI application.
*/
#ifndef lint
static const char rcsid[] = "$Id: threaded.c,v 1.9 2001/11/20 03:23:21 robs Exp $";
#endif /* not lint */
#include "fcgi_config.h"
#include <pthread.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "fcgiapp.h"
#define THREAD_COUNT 20
static int counts[THREAD_COUNT];
static void *doit(void *a)
{
int rc, i, thread_id = (int)a;
pid_t pid = getpid();
FCGX_Request request;
char *server_name;
FCGX_InitRequest(&request, 0, 0);
for (;;)
{
static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Some platforms require accept() serialization, some don't.. */
pthread_mutex_lock(&accept_mutex);
rc = FCGX_Accept_r(&request);
pthread_mutex_unlock(&accept_mutex);
if (rc < 0)
break;
server_name = FCGX_GetParam("SERVER_NAME", request.envp);
FCGX_FPrintF(request.out,
"Content-type: text/html\r\n"
"\r\n"
"<title>FastCGI Hello! (multi-threaded C, fcgiapp library)</title>"
"<h1>FastCGI Hello! (multi-threaded C, fcgiapp library)</h1>"
"Thread %d, Process %ld<p>"
"Request counts for %d threads running on host <i>%s</i><p><code>",
thread_id, pid, THREAD_COUNT, server_name ? server_name : "?");
sleep(2);
pthread_mutex_lock(&counts_mutex);
++counts[thread_id];
for (i = 0; i < THREAD_COUNT; i++)
FCGX_FPrintF(request.out, "%5d " , counts[i]);
pthread_mutex_unlock(&counts_mutex);
FCGX_Finish_r(&request);
}
return NULL;
}
int main(void)
{
int i;
pthread_t id[THREAD_COUNT];
FCGX_Init();
for (i = 1; i < THREAD_COUNT; i++)
pthread_create(&id[i], NULL, doit, (void*)i);
doit(0);
return 0;
}