On Tue, 12 Jan 2010, Szak�ts Viktor wrote:

Hi,

> These calls are missing from hbbmcdx, xhb, rddsql and rddads, 
> maybe it'd be worth to check if they need it or not. I'm 
> still rather unsure when to use it in practice.

The classic example when they have to be executed are .prg
code object destructors. They can be activated at any moment
when some variables is cleared, i.e.:
   hb_itemCopy( pItem, hb_stackReturnItem() );
can activate destructor when clears pItem. If pItem destructor
does not save and restore hb_stackReturnItem() then before coping
the value inside hb_stackReturnItem() will be destroyed.
Destructors should also executed always when possible, it means
that also after BREAK command when function is interrupted
and local variables cleared. So it's necessary to temporary
clear the BREAK signal so PRG code can be executed without
"breaking" by signal set before. Anyhow if HVM is disabled
i.e. released in quite state then we should not allow to
execute any .prg code to not cause GPF. All above problems
are resolved by using hb_vmRequestReenter()/hb_vmRequestRestore()
inside hb_objDestructorCall().
If you plan to reenter HVM in your own pointer item destructors
then you should use safe functions which encapsulate call to
hb_vmProc()/hb_vmSend()/hb_vmDo()/hb_vmFunction() inside
hb_vmRequestReenter()/hb_vmRequestRestore() or make such
encapsulation yourself. If you are creating C API functions
which can be used in different context (i.e. from external code)
then I strongly suggest to save and restore HVM state. Otherwise
some unexpected things can appear in the future.

I remember like few years ago xHarbour users suddenly began to
report problems with very strange in practice unrepeatable RTEs.
For few months such reports were ignored and finally someone
created a code example. After reducing it was sth like:

      proc main()
      [SetWVTCallback()]
      while true() ; enddo
      func true() ; return .T.

It was necessary to link it with GTWVT, run and then systematically
move the mouse pointer over the GT window. After few seconds we had
RTE. Why? Because inside main HVM loop we call periodically:
         hb_inkeyPoll();
and GTWVT user callback function/codeblock without saving/restoring
RETURN value so result of function TRUE() was overwritten sometimes.
When I had looked at it closer I found also other similar problems
and even more dangerous (the initial HVM stack code was operating
on hb_stackTopItem() which was not allocated so reentrant calls were
overwriting it) so I introduced functions to save and restore HVM
state. They were evaluating in last years with other HVM modifications
i.e. I eliminated code like hb_stackTopItem() so it's not longer
necessary to protect the 1-st unused HVM stack item.

If you are still not sure when to use hb_vmRequestReenter()/
hb_vmRequestRestore() then you can use this rule:
If you reeneter HVM from HB_FUNC() or local function which is
called from HB_FUNC() then you do not have to use it. The call
to HB_FUNC() should be already well wrapped so it's not necessary
to repeat the same job. But if you are creating public C functions
which can be called from external code and you do not know the exact
execution context then U suggest to always save and restore HVM state.

I hope that now it's more clear.

best regards,
Przemek
_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to