ACCESS_VIOLATION using ADS Local Server (DBF)

Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

ACCESS_VIOLATION using ADS Local Server (DBF)

Mensaje por ricardo arraes »

hey everybody, I'm not so experienced with ADS, as I said before, so I'm here once again to ask for some help! :D

I'm having troubles with simultaneous requests using DBF tables and the ADS Local server (testing environment)...
when my webservice is processing about 3 requests concurrently which are manipulating the same tables I'm getting a error 6005 ACCESS_VIOLATION callend from DBUSEAREA()


I'm trying to track the problem and found out that from those 3 requests, the first 2 requests were processed as expected, but the third one is unable to open the file and then I get this error I just mentioned...

My function is manipulating the files like that:

Código: Seleccionar todo

caliasage:= NewAlias("PX"+hData['nagenda'])     
    
    USE (  cDirDbf+ "\AGENDA.DBF" ) INDEX "AGENDA"  ALIAS caliasage VIA "ADS" SHARED NEW
    IF NetErr()
        hResponse[ 'success' ] := .T.
        hResponse['cod'] := "7"

        hResponseCrypt['conteudo']:=hb_crypt(hb_jsonEncode(hResponse),AP_GetEnv( "ENCRYPT" ))
        oController:oResponse:SetHeader("Authorization",hCookies)
        oController:oResponse:SendJson( hResponseCrypt )
        RETURN NIL
    ENDIF   

    calias:= Alias(Select(caliasage))
 
newalias() is a function that is creating a Alias dynamically for my table, in order to avoid duplicated alias (advice from Charly)

As I said, I'm using ADS Local Server here in my testing environment, so is there any limitation about the opened tables?
When I'm sending a request that manipulates a table, this request will count as a different "user" (different connection) everytime?
the error in my apache error.log:

Código: Seleccionar todo

Unrecoverable error 6005: Exception error:

    Exception Code:C0000005 ACCESS_VIOLATION
    Exception Address:00007FFB74AB3416
    RAX:0000000000000000  RBX:000001BDA3CAEF60  RCX:000001BDA3CAEF60  RDX:00000000FFFFFFFA
    RSI:0000000000000000  RDI:0000000000000000  RBP:000001BDA3CAEA00
    R8 :0000000000000000  R9 :000001BDA3CAEF00  R10:0000000000000000  R11:00000000122BE5A8
    R12:0000000000000000  R13:000000487FBD6000  R14:0000000000000001  R15:0000000000000000
    CS:RIP:0033:00007FFB74AB3416  SS:RSP:002B:000000487FEFE140
    DS:002B  ES:002B  FS:0053  GS:002B
    Flags:00010213
    Exception Parameters: 0000000000000001 0000000000000024


Modules:

[...]


Called from DBUSEAREA(0)
Called from WS:SALVARCONSULTA(725) in pcode.hrb
Called from __RUNCONTROLLER(9) in pcode.hrb
Called from HB_HRBDO(0)
Called from ZEXECUTE(217) in C:/xampp/htdocs/WSH//lib/mercury/mercury.hrb
Called from TROUTE:EXECUTE(566) in C:/xampp/htdocs/WSH//lib/mercury/mercury.hrb
Called from TROUTE:LISTEN(392) in C:/xampp/htdocs/WSH//lib/mercury/mercury.hrb
Called from TAPP:INIT(139) in C:/xampp/htdocs/WSH//lib/mercury/mercury.hrb
Called from MAIN(16) in pcode.hrb
Called from HB_HRBDO(0)
Called from EXECUTE(70) in ..\source\exec.prg
[Tue Mar 23 17:20:37.854706 2021] [mpm_winnt:notice] [pid 18764:tid 584] AH00428: Parent: child process 9676 exited with status 3221225477 -- Restarting.
The work always comes before the belief
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

I was taking a look at the Advantage Local Server documentation and I found this:
The Advantage Local Server allows both single-user and multiple-user access to data files. The Advantage Local Server file that is installed with Advantage client products contains a physical limitation such that only five or fewer users can concurrently access any table.
https://devzone.advantagedatabase.com/d ... %20Server.

Is it the problem?
The work always comes before the belief
Avatar de Usuario
charly
Mensajes: 145
Registered for: 4 years 8 months

Mensaje por charly »

Ricardo,

Without an example to test it is difficult to find a solution. When using local ads maybe it checks the number of licenses you have that I think I remember that they were 2 by default, I don't remember now

try changing the ADSLOCAL.CFG values the following parameters and experiment

[SETTINGS]
; Advantage Local Server configuration file
;
; The Advantage Local Server DLL (for Windows) and SO (for Linux) reads
; this configuration file when the DLL/SO is loaded. Values input
; after the keyword and equal sign are used to configure the DLL/SO.
; If no value is inserted after a keyword and equal sign, the default
; is used. This file should be located in the same directory as your
; Advantage Local Server DLL (adsloc32.dll) or SO (libadsloc.so).
;
;Maximum Concurrent Users
;Default = 5. Range = 0 - 30.
USER_LICENSE=30
;
; Number of Connections
; Default = 20; Range = 1 - No upper limit
CONNECTIONS=1
Salutacions, saludos, regards.
Charly

"...programar es fácil, hacer programas es difícil..."

https://httpd2.blogspot.com/
https://forum.modharbour.app
Cristobal
Site Admin
Mensajes: 324
Registered for: 4 years 8 months
Spain

Mensaje por Cristobal »

Please, can you put the code that makes the call to the above functions?
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

Hey Charly! Sorry, as was solving some other problems outside the office today, so I didn't have much time to create a good example, but I'm doing it right now...
charly escribió: Mié Mar 24, 2021 8:01 am Ricardo,

Without an example to test it is difficult to find a solution. When using local ads maybe it checks the number of licenses you have that I think I remember that they were 2 by default, I don't remember now

try changing the ADSLOCAL.CFG values the following parameters and experiment

[SETTINGS]
; Advantage Local Server configuration file
;
; The Advantage Local Server DLL (for Windows) and SO (for Linux) reads
; this configuration file when the DLL/SO is loaded. Values input
; after the keyword and equal sign are used to configure the DLL/SO.
; If no value is inserted after a keyword and equal sign, the default
; is used. This file should be located in the same directory as your
; Advantage Local Server DLL (adsloc32.dll) or SO (libadsloc.so).
;
;Maximum Concurrent Users
;Default = 5. Range = 0 - 30.
USER_LICENSE=30
;
; Number of Connections
; Default = 20; Range = 1 - No upper limit
CONNECTIONS=1
But about your comment, I already tried doing what you suggested and still got no luck...

Código: Seleccionar todo

; Number of Connections
; Default = 20; Range = 1 - No upper limit
CONNECTIONS=1
;
; Number of Tables
; Default = 50; Range = 1 - No upper limit
TABLES=119
;
; Number of Index Files
; Default = 75; Range = 1 - No upper limit
INDEXES=119
;
; Number of Data Locks
; Default = 500; Range = 1 - No upper limit
LOCKS=500
;
; Maximum Size of Error Log (in KBytes)
; Default = 1000 KBytes; Range = 1 KByte - No upper limit
ERROR_LOG_MAX=1000
;
; Error Log and Assert Log Path
; Default = C:\
ERROR_ASSERT_LOGS= C:\VFATEC\
;
; ANSI Character Set
; Default = Use the currently configured ANSI character set that is active
;           on the workstation.
; If you do not wish to use the ANSI character set that is active on the
;   current workstation, the available ANSI character sets to be used are:
;     Danish, Dutch, Engl(Amer), Engl(UK), Engl(Can), Finnish, French,
;     French Can, German, Icelandic, Italian, Norwegian, Portuguese, Spanish,
;     Span(Mod), Swedish, Russian, ASCII, Turkish, Polish, Baltic, or
;     Ukrainian
ANSI_CHAR_SET=
;
; OEM/Localized Character Set
; Default = USA
; Options are:
;   USA, DANISH, DUTCH, FINNISH, FRENCH, GERMAN, GREEK437, GREEK851, ICELD850,
;   ICELD861, ITALIAN, NORWEGN, PORTUGUE, SPANISH, SWEDISH, MAZOVIA, PC_LATIN,
;   ISOLATIN, RUSSIAN, NTXCZ852, NTXCZ895, NTXSL852, NTXSL895, NTXHU852,
;   NTXPL852, TURKISH, or BOSNIAN
OEM_CHAR_SET=USA
;
; Local File Flush Frequency (in milliseconds)
; Default = 20000 ms (20 seconds); Range = 0 ms - 100000 ms
FLUSH_FREQUENCY=20000
;
; Lowercase All Paths
; Default = 0 (false)
; Options are: 0 (for false) and 1 (for true)
; Option to force the Linux Advantage Local Server SO to lowercase all
;    paths and filenames before attempting to access them on disk. This
;    option is ignored by the Advantage Local Server DLL for Windows.
LOWERCASE_ALL_PATHS=
WORKAREAS=2500
USER_LICENSE=30

I also tried this configuration:

Código: Seleccionar todo

; Number of Connections
; Default = 20; Range = 1 - No upper limit
CONNECTIONS=100
;
; Number of Tables
; Default = 50; Range = 1 - No upper limit
TABLES=119
;
; Number of Index Files
; Default = 75; Range = 1 - No upper limit
INDEXES=119
;
; Number of Data Locks
; Default = 500; Range = 1 - No upper limit
LOCKS=500
;
; Maximum Size of Error Log (in KBytes)
; Default = 1000 KBytes; Range = 1 KByte - No upper limit
ERROR_LOG_MAX=1000
;
; Error Log and Assert Log Path
; Default = C:\
ERROR_ASSERT_LOGS= C:\VFATEC\
;
; ANSI Character Set
; Default = Use the currently configured ANSI character set that is active
;           on the workstation.
; If you do not wish to use the ANSI character set that is active on the
;   current workstation, the available ANSI character sets to be used are:
;     Danish, Dutch, Engl(Amer), Engl(UK), Engl(Can), Finnish, French,
;     French Can, German, Icelandic, Italian, Norwegian, Portuguese, Spanish,
;     Span(Mod), Swedish, Russian, ASCII, Turkish, Polish, Baltic, or
;     Ukrainian
ANSI_CHAR_SET=
;
; OEM/Localized Character Set
; Default = USA
; Options are:
;   USA, DANISH, DUTCH, FINNISH, FRENCH, GERMAN, GREEK437, GREEK851, ICELD850,
;   ICELD861, ITALIAN, NORWEGN, PORTUGUE, SPANISH, SWEDISH, MAZOVIA, PC_LATIN,
;   ISOLATIN, RUSSIAN, NTXCZ852, NTXCZ895, NTXSL852, NTXSL895, NTXHU852,
;   NTXPL852, TURKISH, or BOSNIAN
OEM_CHAR_SET=USA
;
; Local File Flush Frequency (in milliseconds)
; Default = 20000 ms (20 seconds); Range = 0 ms - 100000 ms
FLUSH_FREQUENCY=20000
;
; Lowercase All Paths
; Default = 0 (false)
; Options are: 0 (for false) and 1 (for true)
; Option to force the Linux Advantage Local Server SO to lowercase all
;    paths and filenames before attempting to access them on disk. This
;    option is ignored by the Advantage Local Server DLL for Windows.
LOWERCASE_ALL_PATHS=
WORKAREAS=2500
USER_LICENSE=30
The work always comes before the belief
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

Yeah, sure, Cristobal!
Cristobal escribió: Mié Mar 24, 2021 10:34 am Please, can you put the code that makes the call to the above functions?
As I said, I got a webservice running with some methods. these methods are called from a website and from a desktop application asynchronously... in other words, there's a great chance that some requests will be sent simultaneously by different users


Let's call it METHOD 1:
*My desktop application is sending requests to this method

Código: Seleccionar todo

METHOD carregarDados(oController) CLASS WS 
LOCAL hData:={=>},hResponse:={=>},hReg:={=>},hRegCrypt:={=>},cDirDbf:= AP_GetEnv( "PATH_DBF" ),cDirAds:= AP_GetEnv( "PATH_ADS" ),;
	  nConn:=0, cAdsSerial:="",nAdsConn:=0, lForcaAds:=.F.,nCons:=0,cUrl:= AP_GetEnv("WSCT")+"updbase", hToken,hCookies,lsend:=.f. ,;
	  hRegAux:={=>},calias,wcmed:="",wnomemed:="",wespdesc:="",lsite:=.F.

	  hData:=oController:oRequest:PostAll()

	  	
	//IDENTIFICA ADS
	DO WHILE .T.

		IF AdsIsServerLoaded( Left(cDirAds,2), @nConn ) = ADS_REMOTE_SERVER
			
			AdsSetServerType(2)
			AdsSetFileType( 2 )
			AdsMgConnect( Left(cDirAds,2),,,@nConn )
			aTemp := AdsMgGetInstallInfo()
			cAdsSerial := IF(Len(aTemp)>=8,aTemp[8],"")
			aTemp := NIL
			nAdsConn := nConn

			
			EXIT

		ELSEIF .NOT. lForcaAds
			AdsSetServerType(1)
			AdsSetFileType( 2 )
			EXIT

		ELSEIF n = 1
			n := 2
		ELSE
			hResponse[ 'success' ] := .F.
			hResponse['cod'] := "7"
				
			oController:oResponse:SendJson( hResponse )
			RETURN NIL
		ENDIF
		
		
	ENDDO	
	
			IF hData['op'] # "I"
				hReg['table'] 	:= 'tabela'
				hReg['cesp'] 	:= hData['reg']
				hReg['op'] 	:= hData['op']
				lsend:=.t.
			ELSE				
				caliasesph:=NewAlias("HC"+StrTran(Time(),":"))				
				
				caliasesp:=NewAlias("EC"+StrTran(Time(),":"))				
				
				caliasdis:= NewAlias("DC"+StrTran(Time(),":"))				
								
				caliasmed:= NewAlias("MC"+StrTran(Time(),":"))							

				TRY 
					USE (  cDirDbf+ "\TABELA1.DBF" ) INDEX "TABELA1"   ALIAS caliasesp VIA "ADS" SHARED NEW
					IF NetErr()
						lsend:=.F.
						QUIT
					ENDIF
				CATCH oError 
					lsend:=.F.
					QUIT
				END 

				caliase:=Alias(Select(caliasesp))
								
				(caliase)->(DbSetOrder(1))		
			
				IF (caliase)->(dbSeek(hData['reg'])) 
					
					wespdesc:=(caliase)->descricao
					lsite:=(caliase)->site

					(caliase)->(dbsetorder(0))
					(caliase)->(dbCloseArea())
					
					hReg['table'] 	:= 'especial'				
					hReg['cesp'] 		:= hData['reg']
					hReg['descricao'] 	:= wespdesc
									
					IF lsite 
						hReg['op'] 	:= hData['op']	
						hReg['medicos']:={}

						TRY 
							USE (  cDirDbf+ "\TABELA2.DBF" ) INDEX "TABELA2"   ALIAS caliasesph VIA "ADS" SHARED NEW				
							IF NetErr()
								lsend:=.F.
								QUIT
							ENDIF
						CATCH oError 
							lsend:=.F.
							QUIT
						END 

						caliash:= Alias(Select(caliasesph))
																
						(caliash)->(DbSetOrder(2))
						
						IF (caliash)->(dbSeek(hData['reg']))

							TRY 
								USE (  cDirDbf+ "\TABELA3.DBF" ) INDEX "TABELA3"  ALIAS caliasmed VIA "ADS" SHARED NEW			
								IF NetErr()
									lsend:=.F.
									QUIT
								ENDIF

								caliasm:=Alias(Select(caliasmed))

								USE (  cDirDbf+ "\TABELA4.DBF" ) INDEX "TABELA4"  ALIAS caliasdis VIA "ADS" SHARED NEW
								IF NetErr()
									lsend:=.F.
									QUIT
								ENDIF
								
								caliasd:=Alias(Select(caliasdis))
							CATCH oError 
								lsend:=.F.
								QUIT
							END 
								
							(caliasm)->(DbSetOrder(1))
							(caliasd)->(DbSetOrder(1))

							DO WHILE (caliash)->cesp=hData['reg'] .AND. .NOT. (caliash)->(Eof())
							
								hRegAux:={=>}
								
								IF (caliasm)->(dbSeek((caliash)->cmed)) .AND. (caliasm)->situacao # "I" .AND. (caliasd)->(dbSeek((caliash)->cmed))
																											
									hRegAux['cmed'] 		:= (caliasm)->cmed
									hRegAux['nome'] 		:= (caliasm)->nome

									hRegAux['especmed']:={}
									hItem:={=>}

									hItem['cmed'] 		:= (caliash)->cmed
									hItem['cesp'] 		:= (caliash)->cesp

									aadd( hRegAux['especmed'], hItem )

									hRegAux['disponib']:={}						
															
									DO WHILE (caliasd)->cmed=(caliasm)->cmed .AND. .NOT. (caliasd)->(Eof())
									
										IF (caliasd)->interval > 0 
											hItem:={=>}

											hItem['cmed'] 		:= (caliasd)->cmed
											hItem['dia'] 		:= (caliasd)->dia
											hItem['hora1'] 		:= (caliasd)->hora1
											hItem['hora2'] 		:= (caliasd)->hora2
											hItem['qte'] 		:= (caliasd)->qte
											hItem['intervalo'] 	:= (caliasd)->interval

											aadd( hRegAux['disponib'], hItem )
										ENDIF

										(caliasd)->(dbSkip())
									ENDDO

									IF Len(hRegAux['disponib'])<=0
										(caliash)->(DbSkip())
										LOOP 
									ELSE 
										Aadd(hReg['medicos'],hRegAux)
									ENDIF
																										
								ENDIF
								
								(caliash)->(dbSkip())
							ENDDO

							(caliasm)->(DbSetOrder(0))
							(caliasm)->(dbCloseArea())

							(caliasd)->(DbSetOrder(0))
							(caliasd)->(dbCloseArea())

							IF Len(hReg['medicos'])<=0
								lsend:=.F.							
							ELSE 
								lsend:=.T.
							ENDIF
						
						ELSE	
							(caliash)->(DbSetOrder(0))
							(caliash)->(dbCloseArea())
							lsend:=.F.						
						ENDIF
						
					ELSE 
						hReg['op'] 	:= "E"					
						lsend:=.t.
					ENDIF
									
					
				ELSE 
					(caliase)->(DbSetOrder(0))
					(caliase)->(dbCloseArea())
					lsend:=.F.
				ENDIF
			ENDIF

	IF lsend
		
		hToken := { 'in' => time(), 'teste' => '000001', 'cnome' => 'WS' }                        
		hCookies := oController:oMiddleware:SetAutenticationToken( hToken )  
		
		hResponse := sendHttp("POST",cUrl,hCookies,hReg)	
		hResponse['cod']:=1
	ELSE 
		hResponse['success']:=.t.
		hResponse['cod']:=2
	ENDIF

	oController:oResponse:SendJson(hResponse)

RETURN NIL


Let's call it METHOD 2:
*My web application is sending requests to this method

Código: Seleccionar todo

METHOD salvarConsulta( oController ) CLASS WS
   	
	local hData := {=>},hDataCrypt	:= {=>},hResponse := {=>},hResponseCrypt := {=>}
    LOCAL cDirDbf:= AP_GetEnv( "PATH_DBF" ),cDirAds:= AP_GetEnv( "PATH_ADS" )
	local aRows,  wnagenda, nConn:=0, cAdsSerial:="",nAdsConn:=0, lForcaAds:=.F.,nCons:=0
	local hCookies := oController:oRequest:GetHeader( 'Authorization' ),calias,caliasage,nQte,nHandle, lError:=.F.
   
    SET EPOCH TO 2000
	SET CENTURY ON
	SET DATE BRITISH
	
	hData:=oController:oRequest:PostAll()	

   
	//IDENTIFICA ADS
   DO WHILE .T.

      IF AdsIsServerLoaded( Left(cDirAds,2), @nConn ) = ADS_REMOTE_SERVER
         AdsSetServerType(2)
		 AdsSetFileType( 2 )
         AdsMgConnect( Left(cDirAds,2),,,@nConn )
         aTemp := AdsMgGetInstallInfo()
         cAdsSerial := IF(Len(aTemp)>=8,aTemp[8],"")
         aTemp := NIL
         nAdsConn := nConn
         EXIT

      ELSEIF .NOT. lForcaAds
         AdsSetServerType(1)
		 AdsSetFileType( 2 )
         EXIT

      ELSEIF n = 1
         n := 2
      ELSE
			//NAO FOI ENCONTRADO O ADS
			hResponse[ 'success' ] := .F.
			hResponse['cod'] := "7"

			oController:oResponse:SetHeader("Authorization",hCookies)
			oController:oResponse:SendJson( hResponse)
			RETURN NIL
      ENDIF
	ENDDO

	caliasage:= NewAlias("PS"+hData['cpaci'])			
	
	TRY 	
		USE (  cDirDbf+ "\TABELA1.DBF" ) INDEX "TABELA1" ALIAS caliasage VIA "ADS" SHARED NEW
			
		IF NetErr()
			lError:=.T.
			hResponse[ 'success' ] := .T.
			hResponse['cod'] := "8"

			hResponseCrypt['conteudo']:=hb_crypt(hb_jsonEncode(hResponse),AP_GetEnv( "ENCRYPT" ))		
		ENDIF
	CATCH oError 
		hResponse[ 'success' ] := .T.
		hResponse['cod'] := "8"

		lError:=.T.
	END 

	IF lError
		oController:oResponse:SetHeader("Authorization",hCookies)
		oController:oResponse:SendJson( hResponse )
		RETURN NIL
	ENDIF 
	
	calias:=Alias(Select(caliasage))	
	
	(calias)->(DbSetOrder(3))
	(calias)->(AdsSetAof("CPACI = ["+ hData['cpaci']+"] AND (SITUACAO <> [C] AND EMPTY(NUMSP)) AND DTOS(DATA) >= ["+Dtos(Date())+"]"))   	

	(calias)->(DbGoTop())
	DO WHILE .NOT. (calias)->(Eof())

		IF (calias)->cmed = hData['cmed']
			
			IF (calias)->hora = StrTran(hData['hora'],":")
				hResponse['cod'] := "5"
			ELSE
				hResponse['cod'] := "9"
			ENDIF

			hResponse['success'] 	:= .T.
			hResponse['nagenda'] 	:= (calias)->nagenda 
			hResponse['cpaci'] 		:= (calias)->cpaci			
			hResponse['cmed'] 		:= (calias)->cmed
			hResponse['situacao'] 	:= (calias)->situacao
			hResponse['data']			:= (calias)->data
			hResponse['hora']			:= (calias)->hora

			(calias)->(AdsClearAof())
			(calias)->(DbSetOrder(0))
			(calias)->(dbCloseArea())	
			
			
			oController:oResponse:SetHeader("Authorization",hCookies)
			oController:oResponse:SendJson( hResponse )
			RETURN NIL

		ENDIF

		nCons++		

		IF nCons >= 3
			//EXCEDEU O LIMITE DE 3 CONSULTAS
			hResponse[ 'success' ] := .F.
			hResponse['cod'] := "6"								

			(calias)->(AdsClearAof())
			(calias)->(DbSetOrder(0))
			(calias)->(dbCloseArea())
			
			
			oController:oResponse:SetHeader("Authorization",hCookies)
			oController:oResponse:SendJson( hResponse )
			RETURN NIL
		ENDIF
	
		(calias)->(DbSkip())
		
	ENDDO
	
	(calias)->(AdsClearAof())
		
	
	(calias)->(DbSetOrder(1))
	(calias)->(dbGoBottom())
	IF (calias)->(Eof())
		wnagenda:="0001"		
	ELSE
		wnagenda:=(calias)->nagenda		
		DO WHILE (calias)->(DbSeek(wnagenda))
			wnagenda:=IncSequenc(wnagenda,4)    		
		ENDDO
	ENDIF	

	nQte:=Seconds()   
	nLOop:=.T.
		
	(calias)->(DbSetOrder(2))
	(calias)->( DbSeek(hData['cmed']+Dtos(Ctod(hData['data']))+StrTran(hData['hora'],":")) )
			
	DO WHILE .NOT. (calias)->(Eof()) .AND. (calias)->data=Ctod(hData['data']) .AND. (calias)->cmed=hData['cmed'] .AND. (calias)->hora=StrTran(hData['hora'],":")
		
		IF (calias)->situacao="N" 

			hResponse['nagenda'] := (calias)->nagenda 
			hResponse['cod']     :="2"
			hResponse['cpaci'] := (calias)->cpaci
			hResponse['success'] := .T.       			
			hResponse['situacao'] := (calias)->situacao

			(calias)->(DbSetOrder(0))
			(calias)->(dbCloseArea())
			
			oController:oResponse:SetHeader("Authorization",hCookies)
			oController:oResponse:SendJson( hResponse )
			RETURN NIL
		ENDIF			

		(calias)->(DbSkip())
				
	ENDDO		
	
	(calias)->(DbSetOrder(0))
	(calias)->(dbAppend())
	IF  NetErr()
					
		nLoop:=.F.
		hResponse[ 'success' ] := .F.
		hResponse['cod'] := "3"
		hResponse['situacao'] := "N"
		
	ELSE 
		
		if (calias)->(DbRLock())
			
			(calias)->nagenda   := wnagenda
			(calias)->data      := Ctod(hData[ 'data' ])
			(calias)->cpaci     := hData[ 'cpaci' ]
			(calias)->cmed      := hData[ 'cmed' ]
			(calias)->hora      := StrTran(hData['hora'],":")
			(calias)->situacao  := "N"
			(calias)->(DbUnLock())
			
			hResponse['nagenda'] 	:= wnagenda
			hResponse[ 'success' ] 	:= .T.
			hResponse['cod'] 			:= "1"
			hResponse['situacao'] 	:= "N"
			hResponse['cpaci'] 		:= hData['cpaci']
			hResponse['cmed'] 		:= (calias)->cmed
			hResponse['data']			:= (calias)->data
			hResponse['hora']			:= (calias)->hora
			
			
		ENDIF
	ENDIF

	
	(calias)->(dbCloseArea())	
	
	oController:oResponse:SetHeader("Authorization",hCookies)
	oController:oResponse:SendJson( hResponse )
	 
RETURN nil


**P.S: the TRY CATCH block was just a test, but it's not preventing the application to crash... it is still crashing and displaying the same error in my apache error.log
The work always comes before the belief
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

oh! and just for the record...

as I said, this two methods will be called asynchronously and - probably - simultanesouly... so the application sometimes is crashing during the METHOD 1 execution, and sometimes during the METHOD 2 execution.

I'm testing this application openning 3 browsers, in different computers (and a mobile), and openning the desktop application. then I'm sending the requests at the same time. Some of the requests are processed as expected, but it reachs a point where the apache crashes as I described...
The work always comes before the belief
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

Update:

tried calling these methods inside new threads like:

Código: Seleccionar todo

METHOD salvarConsulta(oController) CLASS WS 
LOCAL hResponse:={=>},hResponseCrypt:={=>}
	
	if hb_mtvm()
		
		pThreadId = hb_threadStart( @salvarConsultaTh(),oController )
		hb_threadWait( pThreadId )
		hb_threadQuitRequest( pThreadId )
	else
		hResponse[ 'success' ] := .F.
		hResponse['cod'] := "7"

		hResponseCrypt['conteudo']:=hb_crypt(hb_jsonEncode(hResponse),AP_GetEnv( "ENCRYPT" ))
				
		oController:oResponse:SendJson( hResponseCrypt )
	endif 
	hb_gcAll()
	
RETURN NIL

Código: Seleccionar todo

FUNCTION salvarConsultaTh( oController )

...

[SAME AS BEFORE]

...

RETURN NIL

still crashing... :(

BUT I decided to create an route example which I'm opening about 10 tables... and it works fine

so now I know that the problem is not the amount of table being manipulated, probably the problem is one of these:

- amount of users manipulating the tables

*but now I ask you guys... every request to my webserver will be considered as a new "user" for ADS (ADS local)? or it will be considered the same user, because the same application is manipulating all these tables?

- tables being opened at the same exact time (not in a sequence)

Ex: instead of...

USE (TABLE1 )...
USE (TABLE2 )...

these requests are forcing this scenario to happen:

USE (TABLE1)... USE (TABLE2)...

And ADS Local does not allow this to happen



What I am saying here makes any sense? What do you guys think?
The work always comes before the belief
Avatar de Usuario
charly
Mensajes: 145
Registered for: 4 years 8 months

Mensaje por charly »

Ricardo,

As I told you, it is very difficult to find a solution without an example. If you provide a small self-contained example, along with the dlls + example tables + ... maybe I can experiment and try to find a solution.

The example below that you show using threads, I think it does not make sense, because each request that Apache collects already processes it by threads and it does not make sense (apart from the fact that it may be an error) to create another.

We must be able to reproduce the error in order to try to solve it
Salutacions, saludos, regards.
Charly

"...programar es fácil, hacer programas es difícil..."

https://httpd2.blogspot.com/
https://forum.modharbour.app
Avatar de Usuario
ricardo arraes
Mensajes: 87
Registered for: 4 years 8 months
Brazil

Mensaje por ricardo arraes »

I know, Charly, without an example I know it makes harder to understand...
the problem was that I couldn't figure out what was the REAL problem and which exactly moment the error was happening...

So I coundn't create a precise example of what was happening...
charly escribió: Jue Mar 25, 2021 7:57 am Ricardo,

As I told you, it is very difficult to find a solution without an example. If you provide a small self-contained example, along with the dlls + example tables + ... maybe I can experiment and try to find a solution.

The example below that you show using threads, I think it does not make sense, because each request that Apache collects already processes it by threads and it does not make sense (apart from the fact that it may be an error) to create another.

We must be able to reproduce the error in order to try to solve it
But NOW...

I figured out what was happening and the problem is that situation that I mentioned:
- tables being opened at the same exact time (not in a sequence)

Ex: instead of...

USE (TABLE1 )...
USE (TABLE2 )...

these requests are forcing this scenario to happen:

USE (TABLE1)... USE (TABLE2)...
As I said, I got 2 or more requests being processed simultaneously... so it's possible that in any moment it's trying to open tables in the SAME EXACT moment by the same "user"/connection (my webservice)... which I believe is not allowed by ADS Local (correct if I'm wrong).

I just created I way of preventing this to happen, and it seems to be working, but I need to test a little bit more before posting here as a solution.

now that everything is well understood, I'll send you guys a new simple example soon! :)
The work always comes before the belief
Responder