VO Question: dbServer FieldGET issue

Public support forum for peer to peer support with related to the Visual Objects and Vulcan.NET products
ic2
Posts: 1858
Joined: Sun Feb 28, 2016 11:30 pm
Location: Holland

VO Question: dbServer FieldGET issue

Post by ic2 »

Hello Jamal,

Good detective work!

Please keep us posted about what Joachim replies.

Dick
Jamal
Posts: 322
Joined: Mon Jul 03, 2017 7:02 pm

VO Question: dbServer FieldGET issue

Post by Jamal »

Hi All,

Joachim just replied and could not duplicate the issue.

In the mean time I think I may have found out the culprit: it has to do with multi-threading and DBF workarea gets all mixed up.

Disclaimer: I am no multi-threading expert, my conclusions may not be accurate.

I was creating a timer using code like the incomplete sample below. When the timer kicked in, the OpenDBFCallBack() is called. This function only opens another DBF, checks some values, closes dbServer and returns, but somehow, this affected bBrowser dbServer workarea in another unrelated datawindow1 where a bBrowser:refresh() was called by its refresh timer. The workarea got overwritten and no longer the same and thus FIELDGET("SOMEFIELD") crashed because my code that handles bBrowser on DataWindow1 innocently thinks it is still working with the same original workarea and its same dbf structure.

Here the a sample code:

_dll FUNCTION CreateTimerQueue() as ptr PASCAL:Kernel32.CreateTimerQueue

Code: Select all


function Test() as void pascal 
 	local hTimer as ptr
 	local arg := 1234 as int
       local gDoneEvent as ptr   
       LOCAL gTimerQueue as ptr

 	gDoneEvent := CreateEvent(null_ptr, true, FALSE, null_ptr)

 	// Create the timer queue.
 	gTimerQueue := CreateTimerQueue()

 	// Set a timer to call the timer routine every 5 minutes.
       //  Time in milliseconds. Multiply the time value by 60000. 5 MINUTES = 5*60000 
 	CreateTimerQueueTimer( @hTimer, gTimerQueue, @OpenDBFCallBack(), @arg , 1*60000, 1*60000, 0)

	return

function OpenDBFCallBack() as void pascal
// open dbf server, check some values
// close dbServer and return
return

Note: even before using the above CreateTimerQueueTimer(), I had issues with bBrowser sometimes failing with similar issues.

I had DbSetRestoreWorkarea(false) in the Start() of my app. I will do more tests to see if setting it to True makes a difference.

Jamal
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

VO Question: dbServer FieldGET issue

Post by wriedmann »

Hi Jamal,
if you are not using multithreading in your application, then this is not the cause.
In VO both the RDDs and the Garbage Collector are no thread safe, but according to the Microsoft docs https://docs.microsoft.com/de-de/window ... mer-queues this call does not creates an own thread.
There must be something other that confused the runtime and make it close the wrong server.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Jamal
Posts: 322
Joined: Mon Jul 03, 2017 7:02 pm

VO Question: dbServer FieldGET issue

Post by Jamal »

Hi Wolfgang,

You most likely right. If you notice I wrote:
Note: even before using the above CreateTimerQueueTimer(), I had issues with bBrowser sometimes failing with similar issues.

But my feeling is that it has to do with the way VO is handling works areas and may be the DbSetRestoreWorkarea(false) is the cause. I can't rule anything out at this point.

Jamal
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

VO Question: dbServer FieldGET issue

Post by wriedmann »

Hi Jamal,

yes, I have noted that.
But in my applications (and I'm using bBrowser heavily) I had never this issue.
Do you are using a hybrid approach somewhere (mixed functions and servers9?
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Jamal
Posts: 322
Joined: Mon Jul 03, 2017 7:02 pm

VO Question: dbServer FieldGET issue

Post by Jamal »

Hi Wolfgang,

It use mostly dbServer methods in my apps, and if I overrode any dbServer methods (for speed) I write for example:

Code: Select all

METHOD FIELDPUT( uField, uValue ) CLASS _JamalDBServer

	LOCAL wPos as DWORD
	LOCAL dwCurrentWorkArea as DWORD

	
	VODBSelect( wWorkArea, @dwCurrentWorkArea ) // select workrea
	
	wPos := __GetFldPos( uField, wFieldCount )
	
	VODBFieldPut( wPos, uValue )
	
	__DBSSetSelect( dwCurrentWorkArea )  //SE-060527  - restore workarea

	RETURN uValue   
Jamal
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am
Location: Germany

VO Question: dbServer FieldGET issue

Post by Karl-Heinz »

Hi Jamal,

take a look at the __DBSSetSelect() sources. If you don´t use the DbSetRestoreWorkarea(TRUE) setting, the global var __glRestoreWorkarea never becomes true. So either use DbSetRestoreWorkarea(TRUE) or restore the workarea within your FieldPut()

Code: Select all

FUNCTION __DBSSetSelect(dwNew AS DWORD) AS DWORD PASCAL
   //SE-060527
   IF __glRestoreWorkarea    <---------------------------------------
      RETURN VODBSetSelect(LONGINT(dwNew))
   ENDIF
   RETURN dwNew
regards
Karl-Heinz
User avatar
robert
Posts: 4537
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

VO Question: dbServer FieldGET issue

Post by robert »

Jamal, Karl-Heinz,

I suggest to set DbSetRestoreWorkarea(TRUE) .
In fact I will make that the default for the next build.
In VO switching workareas (especially when there are many fields) can be quite expensive. The runtime removes the fieldnames from the active table from the memvar/fields list and then adds the fields of the new area.
We added this setting as optimization.
But in X# things work differently, so there is no need anymore to suppress workarea switching. See
https://github.com/X-Sharp/XSharpPublic ... .prg#L1694
to see what we are doing: we are only changing the active workarea number.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Jamal
Posts: 322
Joined: Mon Jul 03, 2017 7:02 pm

VO Question: dbServer FieldGET issue

Post by Jamal »

Hi Karl, Robert,

I will use DbSetRestoreWorkarea(TRUE) from now on in my VO apps.

Hopefully, this cures the issues.

Jamal
Post Reply