From b8b600f2cb761bff764a3f54eaf964ddb11c857d Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Sat, 7 Mar 2009 18:51:08 +0000 Subject: [PATCH] 2009-03-07 19:56 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/common/hbgete.c * added suport for BSD systems * harbour/contrib/examples/uhttpd/uhttpd.prg ! fixed private declaration - after last modification they were not declared for threads at all ! fixed close procedure, s_aRunningThreads and s_aServiceThreads where not protected at all in the moment when these variables variables where used inside aeval() and other threads were resizing them removing their pointers. In short word it was in practice impossible to cleanly close uhttpd server without GPF, deadlock or other bad side effects. I changed this code so these arrays are modified only by calling procedure. I do not know why it was written in such way but I guess it was workaround for xHarbour bugs. In xHarbour is race condition inside some functions like ThreadJoin() (RTE if thread finished just before ThreadJoin()). Harbour does not have such problems so I simply cleaned this code making it much simpler. * reactivated hb_gcAll( .T. ) in the main loop for tests. I made some tests with linux and current uhttpd works perfectly without any problems with and without hb_gcAll( .t. ). I haven't noticed any problems. I used this scripts to make tests: #!/bin/sh function GT_UHTTPD() { while curl http://127.0.0.1:8082/ > /dev/null do if ! curl http://127.0.0.1:8082/serverstatus > /dev/null then exit fi # disable it if you want to increase traffic if ! curl http://127.0.0.1:8082/info > /dev/null then exit fi if [ -f stop ] then exit fi done } for i in `seq 10` do GT_UHTTPD &>/dev/null & done wait on three CPU machine. Please make some test with other systems. --- harbour/ChangeLog | 52 ++++++++++++++++++++++ harbour/contrib/examples/uhttpd/uhttpd.prg | 32 +++++++------ harbour/source/common/hbgete.c | 2 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 02db5b82dd..d65db76649 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,58 @@ 2009-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org) */ +2009-03-07 19:56 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/source/common/hbgete.c + * added suport for BSD systems + + * harbour/contrib/examples/uhttpd/uhttpd.prg + ! fixed private declaration - after last modification they were not + declared for threads at all + ! fixed close procedure, s_aRunningThreads and s_aServiceThreads + where not protected at all in the moment when these variables + variables where used inside aeval() and other threads were + resizing them removing their pointers. In short word it was + in practice impossible to cleanly close uhttpd server without + GPF, deadlock or other bad side effects. I changed this code so + these arrays are modified only by calling procedure. + I do not know why it was written in such way but I guess it + was workaround for xHarbour bugs. In xHarbour is race condition + inside some functions like ThreadJoin() (RTE if thread finished + just before ThreadJoin()). Harbour does not have such + problems so I simply cleaned this code making it much simpler. + * reactivated hb_gcAll( .T. ) in the main loop for tests. + I made some tests with linux and current uhttpd works perfectly + without any problems with and without hb_gcAll( .t. ). + I haven't noticed any problems. I used this scripts to make + tests: + #!/bin/sh + function GT_UHTTPD() + { + while curl http://127.0.0.1:8082/ > /dev/null + do + if ! curl http://127.0.0.1:8082/serverstatus > /dev/null + then + exit + fi + # disable it if you want to increase traffic + if ! curl http://127.0.0.1:8082/info > /dev/null + then + exit + fi + if [ -f stop ] + then + exit + fi + done + } + for i in `seq 10` + do + GT_UHTTPD &>/dev/null & + done + wait + + on three CPU machine. Please make some test with other systems. + 2009-03-07 13:04 UTC+0100 Viktor Szakats (harbour.01 syenar hu) * contrib/examples/uhttpd/uhttpdgd.hbm + Added *nix GD lib name. diff --git a/harbour/contrib/examples/uhttpd/uhttpd.prg b/harbour/contrib/examples/uhttpd/uhttpd.prg index 51b21e0b69..e2222ad1bb 100644 --- a/harbour/contrib/examples/uhttpd/uhttpd.prg +++ b/harbour/contrib/examples/uhttpd/uhttpd.prg @@ -210,8 +210,6 @@ FUNCTION MAIN( ... ) LOCAL hDefault, cLogAccess, cLogError, cSessionPath LOCAL cCmdPort, cCmdDocumentRoot, lCmdIndexes, nCmdStartThreads, nCmdMaxThreads - PRIVATE _SERVER, _GET, _POST, _COOKIE, _SESSION, _REQUEST, _HTTP_REQUEST, m_cPost - IF !HB_MTVM() ? "I need multhread support. Please, recompile me!" WAIT @@ -554,7 +552,7 @@ FUNCTION MAIN( ... ) ENDIF // Memory release - //hb_GCAll( TRUE ) + hb_GCAll( TRUE ) ENDDO @@ -632,14 +630,21 @@ STATIC FUNCTION AcceptConnections() // Requesting to Running threads to quit (using -1 value) AEVAL( s_aRunningThreads, {|| hb_mutexNotify( s_hmtxRunningThreads, -1 ) } ) - // waiting running threads to quit - AEVAL( s_aRunningThreads, {|h| hb_threadJoin( h ) } ) - // Requesting to Service threads to quit (using -1 value) AEVAL( s_aServiceThreads, {|| hb_mutexNotify( s_hmtxServiceThreads, -1 ) } ) + + // waiting running threads to quit + AEVAL( s_aRunningThreads, {|h| hb_threadJoin( h ) } ) // waiting service threads to quit AEVAL( s_aServiceThreads, {|h| hb_threadJoin( h ) } ) + IF hb_mutexLock( s_hmtxBusy ) + //hb_ToOutDebug( "Len( s_aRunningThreads ) = %i\n\r", Len( s_aRunningThreads ) ) + asize( s_aRunningThreads, 0 ) + asize( s_aServiceThreads, 0 ) + hb_mutexUnlock( s_hmtxBusy ) + ENDIF + EXIT ENDIF @@ -718,6 +723,8 @@ STATIC FUNCTION ProcessConnection() LOCAL hSocket, nLen, cRequest, cSend LOCAL nMsecs, nParseTime, nPos, nThreadID + PRIVATE _SERVER, _GET, _POST, _COOKIE, _SESSION, _REQUEST, _HTTP_REQUEST, m_cPost + nThreadId := hb_threadID() //hb_ToOutDebug( "nThreadId = %s\r\n", nThreadId ) @@ -842,14 +849,6 @@ STATIC FUNCTION ProcessConnection() WriteToConsole( "Quitting ProcessConnections() " + hb_CStr( nThreadId ) ) - IF hb_mutexLock( s_hmtxBusy ) - //hb_ToOutDebug( "Len( s_aRunningThreads ) = %i\n\r", Len( s_aRunningThreads ) ) - IF ( nPos := aScan( s_aRunningThreads, hb_threadSelf() ) > 0 ) - hb_aDel( s_aRunningThreads, nPos, TRUE ) - s_nThreads := Len( s_aRunningThreads ) - ENDIF - hb_mutexUnlock( s_hmtxBusy ) - ENDIF RETURN 0 @@ -858,6 +857,8 @@ STATIC FUNCTION ServiceConnection() LOCAL nMsecs, nParseTime, nPos, nThreadId LOCAL nError := 500013 + PRIVATE _SERVER, _GET, _POST, _COOKIE, _SESSION, _REQUEST, _HTTP_REQUEST, m_cPost + ErrorBlock( { | oError | uhttpd_DefError( oError ) } ) nThreadId := hb_threadID() @@ -977,9 +978,6 @@ STATIC FUNCTION ServiceConnection() IF hb_mutexLock( s_hmtxBusy ) s_nServiceThreads-- - IF ( nPos := aScan( s_aServiceThreads, hb_threadSelf() ) > 0 ) - hb_aDel( s_aServiceThreads, nPos, TRUE ) - ENDIF hb_mutexUnlock( s_hmtxBusy ) ENDIF diff --git a/harbour/source/common/hbgete.c b/harbour/source/common/hbgete.c index 3241b654ae..3f54057a54 100644 --- a/harbour/source/common/hbgete.c +++ b/harbour/source/common/hbgete.c @@ -158,7 +158,7 @@ BOOL hb_setenv( const char * szName, const char * szValue ) #elif defined( _BSD_SOURCE ) || _POSIX_C_SOURCE >= 200112L || \ _XOPEN_SOURCE >= 600 || defined( __WATCOMC__ ) || defined( __DJGPP__ ) || \ - defined( HB_OS_DARWIN ) + defined( HB_OS_BSD ) || defined( HB_OS_DARWIN ) if( szValue ) return setenv( szName, szValue, 1 ) == 0;