On Wed, 12 Nov 2008, Pritpal Bedi wrote:
Hi Pritpal,
> I wonder why I took a long route whereas the shortest and
> neatest was awailable.
Please try to read carefully the text below. If you will not
understand sth then please ask about it. I'll try to help but
I need that you will want to create really MT safe code not a
code which sometimes can work without a crash.
> I changed the name to HB_GTINFOEX and kept this code in gtwvg.c.
> It gets me what I require. To function it properly as per my needs,
> I had to issue instead of
>
> HB_GTSELF_INFO( pGT, hb_parni( 2 ), >Info );
> hb_gt_BaseFree( pGT );
>
>
> hb_gt_BaseFree( pGT );
> HB_GTSELF_INFO( pGT, hb_parni( 2 ), >Info );
The above modification confirms that the problem is in your code.
> I have to release the lock before I fetch the values otherwise
> current GT remains locked forever. In theory it should not happen but
> happens. Possibly how I am trying to use it havethis side effect.
You should locate the exact reason or you may have unexpected
behaviour in final MT applications. GT uses recursive locks.
It means that one thread can lock GT many times and then should
unlock it the same number of times to make it available for
other threads. If in your code calling GTINFO with locked GT
is a problem then it means that you created deadlock because
some of your code depends on unlocked access to GT structure
and other threads also operate on this GT and probably try to
lock other GTs. You can remove all locks and maybe it will
work and only sometimes crashes when two threads will begin to
change the same data in the same code. It's even possible that
on single CPU machine the problem will not be exploited and
will crash only on real CPU machines. But it does not mean that
the code is correct. Probably the problem is caused by the fact
that in Windows some operations on window structure can be done
_ONLY_ by the thread which created the window and all other threads
which try to execute them are blocked until the thread which is
window owner will not execute them. 10 against 1 that you have
such situation inside INFO method and when it's executed with
locked GT driver it's stopped until window owner thread will
not make it. And it cannot make it because GT is locked. Such
deadlock existed in pure GTWVT when SendMessage() was used instead
of SendNotifyMessage(). SendMessage blocks thread which executed
this function untill thread which is window owner will not process
this message. When it's the same thread then it's not a problem.
When it's other thread then we have deadlock because it is not
able to enter GT structure and process messages because GT is
locked by thread which waits on SendMessage(). To resolve it
I changed all SendMessage() calls to SendNotifyMessage(). But
I do not check all other functions you are adding as INFO method
actions if they do not have the same problem, f.e. they can
internally call SendMessage(). I hope that anyone adding such
new function call to GTWVT will check in MSDN documentation if
such things can happen and if it's a problem then will use
alternative function or parameters to avoid blocking. When
it's impossible then he should unlock GT driver before calling
blocking function and then lock it again. F.e. if I want to
force that message send to window will be processed instead of
leaving it in a queue only then I can use SendMessage() instead
of SendNotifyMessage() in the following way:
HB_GTSELF_UNLOCK( pGT ); // unlock GT driver for other threads
// and hWND owner which can be different
// thread then current one.
SendMessage( hWND, .... );
HB_GTSELF_LOCK( pGT ); // lock the GT to be sure that other
// threads does not manipulate on pGT
// structure.
and the problem of deadlock will be resolved. This is proper solution
and you are asking about removing GT locking inside new function
hb_gtInfoEX() because you created code which produce deadlock and
this is sufficient workaround for you without checking the reason
of problem or what wrong may happen when other thread is accessing
the GT structure you are using. And then we have reports like Viktor
that sth can crash after some mouse manipulation. It's possible but
because the problem is exploited by race condition due to missing
mutex protection then it's not be easy repeatable and the same code
can work fine executed 1000 times and will crash in 1001 test or
in 101 when real multi CPU machine is used.
If at beginning you will create a lot of such code then fixing it
later will be a nightmare. Probably it will be easier to rewrote
it from scratch what sometimes is even good idea because you should
know all final conditions and you can design it in better way :-)
> I understand your viewpoint and investigating more.
> Perhaps at the point I call this function I do not need it to be locked
> because I am already on another GT which is in the diaplay process.
If you read carefully above text then you will find that your thread
is blocked untill other thread which is window owner will lock GT
structure and process all pending messages unblocking your thread.
In MS-Window only thread which created window can process its messages
so two thread are entering the same GT structure in the same time without
any synchronization code.
BTW In GTWVG is a function:
PHB_GTWVT hb_wvt_gtGetWVT( void );
which return pointer to PHB_GTWVT but the GT is unlocked. It means that
you need your own protection code for accessing this GT or better you
should change this function and remove hb_gt_BaseFree() adding corresponding
function:
void hb_wvt_gtFreeWVT( PHB_GTWVT pWVT )
{
hb_gt_BaseFree( pWVT->pGT );
}
which will be called when you finished all operations on pWVT.
best reagrds,
Przemek
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour