BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

D2006 memory leak (and potential AV) in SoapHTTPClient.Pas

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi WebServices SOAP
View previous topic :: View next topic  
Author Message
danny heijl
Guest





PostPosted: Fri Mar 30, 2007 1:13 am    Post subject: D2006 memory leak (and potential AV) in SoapHTTPClient.Pas Reply with quote



There is a memory leak in SoapHTTPClient.pas: the constructor takes a
copy of the interfaced objects FDefaultDomConvertor and FDefaultWebNode
but the destructor does not release the copies of these interfaces.

When using SSL with client certificates (a simple patch in the soap http
transport will enable this) for soap, this can lead to an access
violation in the CSP for the certificate used by Wininet. Because the
interface using WinInet is not freed, the WinInet handles are not freed,
and when the program has terminated, and Windows unloads the DLL's,
WinInet tries to free the certificate context used for the SSL (*after*
the Delphi runtime has done it's cleanup) you get an access violation
because everything else has long gone.

The following change remedies the problem (and the memory leak):


destructor THTTPRIO.Destroy;
begin
if Assigned(FConverter) then
FConverter := nil;
if Assigned(FDOMConverter) then // -- added dh --
FDOMConverter := Nil; //
if Assigned(FWebNode) then
FWebNode := nil;
if Assigned(FHTTPWebNode) then // -- added dh --
FHTTPWebNode := Nil; //
if Assigned(FWSDLView) then
FWSDLView.Free;

{ All components we own are automatically cleaned up }
inherited;
end;

Danny
---
Back to top
Jean-Marie Babet
Guest





PostPosted: Fri Mar 30, 2007 3:26 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote



Hello Danny,

I need more information. FHTTPWebNode and FDomConverter point to instances
of TOpToSoapDomConvert and THTTPReqResp respectively. We manage their
lifetime via the FConverter and FWebNode interfaces. IOW, the constructor
does this:

{ Converter }
FDomConverter := GetDefaultConverter;
FConverter := FDomConverter as IOPConvert;
{ WebNode }
FHTTPWebNode := GetDefaultWebNode;
FWebNode := FHTTPWebNode as IWebNode;

The destructor does

FConverter := nil;
FWebNode := nil;

Clearing out the FConvert and FWebNodes interfaces should free the objects
pointed to by FDomConvert and FHTTPWebNode respectively(*). You can clear
the two fields pointing to the actual objects but that won't affect the
lifetime of the objects; it's probably a good idea to catch cases where
someone might attempt to reuse a freed THTTPRIO object.

If you step through the code in the debugger you should see that the
destructor is invoked when the interface is cleared.

Am I missing something?

Thank you,

Bruneau.





(*) PS: Clearing the interfaces won't free the objects if some other
interface holds a refcount on these objects. In this case since we're the
only one who retrieves the interface, we're safe - unless someone's code
adds one or more refcount on these objects.




"Danny heijl" <danny.heijl (AT) telenet (DOT) be> wrote in message
news:euh6rh$dpv1 (AT) bornews (DOT) inprise.com...
Quote:
There is a memory leak in SoapHTTPClient.pas: the constructor takes a
copy of the interfaced objects FDefaultDomConvertor and FDefaultWebNode
but the destructor does not release the copies of these interfaces.

When using SSL with client certificates (a simple patch in the soap http
transport will enable this) for soap, this can lead to an access
violation in the CSP for the certificate used by Wininet. Because the
interface using WinInet is not freed, the WinInet handles are not freed,
and when the program has terminated, and Windows unloads the DLL's,
WinInet tries to free the certificate context used for the SSL (*after*
the Delphi runtime has done it's cleanup) you get an access violation
because everything else has long gone.

The following change remedies the problem (and the memory leak):


destructor THTTPRIO.Destroy;
begin
if Assigned(FConverter) then
FConverter := nil;
if Assigned(FDOMConverter) then // -- added dh --
FDOMConverter := Nil; //
if Assigned(FWebNode) then
FWebNode := nil;
if Assigned(FHTTPWebNode) then // -- added dh --
FHTTPWebNode := Nil; //
if Assigned(FWSDLView) then
FWSDLView.Free;

{ All components we own are automatically cleaned up }
inherited;
end;

Danny
---


"danny heijl" <danny_dot_heijl_at_telenet_dot_be> wrote in message
news:460c1e06$1 (AT) newsgroups (DOT) borland.com...
Quote:
There is a memory leak in SoapHTTPClient.pas: the constructor takes a
copy of the interfaced objects FDefaultDomConvertor and FDefaultWebNode
but the destructor does not release the copies of these interfaces.

When using SSL with client certificates (a simple patch in the soap http
transport will enable this) for soap, this can lead to an access
violation in the CSP for the certificate used by Wininet. Because the
interface using WinInet is not freed, the WinInet handles are not freed,
and when the program has terminated, and Windows unloads the DLL's,
WinInet tries to free the certificate context used for the SSL (*after*
the Delphi runtime has done it's cleanup) you get an access violation
because everything else has long gone.

The following change remedies the problem (and the memory leak):


destructor THTTPRIO.Destroy;
begin
if Assigned(FConverter) then
FConverter := nil;
if Assigned(FDOMConverter) then // -- added dh --
FDOMConverter := Nil; //
if Assigned(FWebNode) then
FWebNode := nil;
if Assigned(FHTTPWebNode) then // -- added dh --
FHTTPWebNode := Nil; //
if Assigned(FWSDLView) then
FWSDLView.Free;

{ All components we own are automatically cleaned up }
inherited;
end;

Danny
---
Back to top
danny heijl
Guest





PostPosted: Fri Mar 30, 2007 8:13 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote



Jean-Marie Babet schreef:

Quote:
Am I missing something?

I don't know, but when I set a breakpoint on the "inherited" line in the
destructor (the last line of the method):

Quote:
{ All components we own are automatically cleaned up }
inherited;

the fields FHTTPWebNode and FWebNode stil point to what seem to be valid
instances in the debugger.

When I clear those 2 fields I no longer get the crash in the CSP.

Danny
---
Back to top
Jean-Marie Babet
Guest





PostPosted: Fri Mar 30, 2007 10:52 pm    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Hello,

Quote:
the fields FHTTPWebNode and FWebNode stil point to what seem to be valid
instances in the debugger.

I assume you meant FHTTPWebNode and FDOMConverter. Yes, they'll point to
valid memory but that memory has been freed. They can point there - bit
can't touch it.

If you get an AV in inherited, this means that somehow the base class
destructor is accessing these fields but they are gone, hence the AV. It's
safe to nil fields that point to objects but nilling the field does not
destroy/free them. For an object, one has to call Object.Free to cleanup.
For an interface nilling the field will free the object (provided no one
else is holding a reference to the object).

If you can provide me a testcase of this issue, I'd like to investigate.
Does this happen on a vanilla THTTPRIO?

Cheers,

Bruneau.
Back to top
danny heijl
Guest





PostPosted: Sat Mar 31, 2007 12:17 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Jean-Marie Babet schreef:

Quote:
If you can provide me a testcase of this issue, I'd like to investigate.

You would need a Belgian Electronic Identity card for that (it would be
rather difficult for you to obtain one) and install the corresponding CSP.

Quote:
Does this happen on a vanilla THTTPRIO?

Unfortunately a "vanilla" THHTPRIO does not allow the use of client
certificates.

The only change I made was to pass on a PCCERT_CONTEXT property so that
it can be set in the appropriate WinInet option. WinInet then does a
CertDuplicateCertificateContext so that the original CERT_CONTEXT can
safely be freed.

The webservice works without any problems, I can call any method as many
times as I like but when I shut down the webservice client the app
crashes in the EID CSP on the dll unload code of the CSP.

With those 2 fields cleared the crash does not occur. I don't understand
what difference this can make because they are just 2 object references
and not interface references as you pointed out, so that the object
finalizer will not attempt to Release them.

It could be a bug in the CSP, but I don't see the connection with those
2 fields not being cleared.

Danny
---
Back to top
Jean-Marie Babet
Guest





PostPosted: Sat Mar 31, 2007 2:00 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Hello,

Quote:
The webservice works without any problems, I can call any method as many
times as I like but when I shut down the webservice client the app
crashes in the EID CSP on the dll unload code of the CSP.

With those 2 fields cleared the crash does not occur. I don't understand
what difference this can make because they are just 2 object references
and not interface references as you pointed out, so that the object
finalizer will not attempt to Release them.

It could be a bug in the CSP, but I don't see the connection with those
2 fields not being cleared.


Ummmm, could it be the following ?

There are two ways to use THTTPRIO. You can create it with (nil) as
parameter or you can drop one on a form (or DataModule), in which case it's
created with a parent component.

If the HTTPRIO is created with (nil), when you're done with your WebService
interface, the RIO goes away and we're fine. However, if the RIO is created
as a component (i.e. passed a non-nil value in constructor, or dropped on a
form or data module), then there's something that you have to be aware of:
releasing the WebService interface will not free the RIO. Rather, the RIO is
freed by its parent component. But more importantly, when the interface
representing the webservice goes away, it will attempt to destroy the its
underlying RIO. The latter will resist but *IF* the latter is already gone,
you'll get an AV in the destructor. Let me illustrate a sample:

Say I have a form that accesses Amazon to search for items:

TAWSEForm = class(TForm)
HTTPRIO1: THTTPRIO;
Search: TButton;
procedure SearchClick(Sender: TObject);
private
{ Private declarations }
FAmazonWS: AWSECommerceServicePortType;
public
{ Public declarations }
end;

The form has an HTTPRIO, a Button and a field, FAmazonWS, to hold the
interface to the service.

When the button is clicked I do something like this:


procedure TAWSEForm.SearchClick(Sender: TObject);
begin
if FAmazonWS = nil then
FAmazonWS := HTTPRIO1 as AWSECommerceServicePortType;
Response := FAmazonWS.ItemSearch(Request);
{ I'm leaving out the details of the call }
end;


The above will crash in the destructor of the THTTPRIO upon exit. The reason
is because when the Form is being destroyed, it will destroy the HTTPRIO
component. But then later the 'FAmazonWS' field will be released (by code
generated automatically by Delphi) and the call to Release will access the
THTTPRIO that's gone.

The solution for the above is one of the following:

(a) Either don't use the HTTPRIO as a component. Create it dynamically with
THTTPRIO.Create(nil). Of course that's not so attractive since as a
component you get to use the Object Inspector to set default values and the
IDE generates/manages event handlers, etc... So the other solution is:

(b) Make sure that all interfaces to a component HTTPRIO are released
*before* the component is destroyed. In the above case, this means clearing
the interface in the FormDestroy at latest - as in:

procedure TAWSEForm.FormDestroy(Sender: TObject);
begin
FAmazonWS := nil;
end;


With the above code, you won't get an AV in the destructor of THTTPRIO.
Without the code in the FormDestroy, the above code will AV.

I'm not sure whether the above applies to your scenario but it's a common
stumbling block because unlike most other VCL components, the SOAP ones have
this dual lifetime management styles: as an interface or as a component.

If the above is not the case then, yes, do add the nil to the destructors as
that's what works for you. And if you ever find out more, I'd like to hear
about it as there's something not quite right with the AVs.

Cheers,

Bruneau.
Back to top
danny heijl
Guest





PostPosted: Sun Apr 01, 2007 2:08 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Jean-Marie Babet schreef:

Quote:
Ummmm, could it be the following ?

Thanks for the long explanation, but (alas) this is not the problem. I
never paint these interfaced components in the designer, but always
create them in code without an owner, so that I don't have to worry
about who's responsible for freeing, I know it's me.

Fastmm in full debug mode does not see anything wrong either.

Danny
---
Back to top
Jean-Marie Babet
Guest





PostPosted: Sun Apr 01, 2007 2:51 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Hello Danny,

I doubled check that FastMM was on after reading your first post. I enabled
FastMM for all our unit tests a few months ago and it did find several
issues that I've addressed.

There are a few other anomalies about TRIO-based types that can cause
problems but they are rather esoteric. The main one is related to the fact
that the RIO object makes up vtables and does not benefit from the
compiler's normal codegen. The AddRef/Release/QI of the manufactured vtables
cannot be invoked from the RIO itself because these methods expect 'Self' to
require explicit adjustment (something that the compiler would do in normal
cases).

I would be happy to look at any excerpts of your RIO-based type that you can
share to see if I can spot anything. Feel free to email me at
bbabet (AT) codegear (DOT) com. Also, if time allows, it might be useful to look at the
CPU window while stepping through the destructor - to see where the AV
occurs (in TRIO's destructor? In prologue/epilogue code generated by
compiler?).

Cheers,

Bruneau.
Back to top
danny heijl
Guest





PostPosted: Mon Apr 02, 2007 12:56 am    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Jean-Marie Babet schreef:

Quote:
Also, if time allows, it might be useful to look at the
CPU window while stepping through the destructor - to see where the AV
occurs (in TRIO's destructor? In prologue/epilogue code generated by
compiler?).

The crash consistently happens in the "dll unload" code of the CSP which
is called by Windows (not through Delphi code), long after the TRIO
destructor has finished.

Interfaces are a real nuisance here because you can't control the time
of actual destruction and resource release, and with certificates the
sequence of events is important because you can't use a certificate with
it's CSP if the certificate store associated with a certificate is not
open, but to release resources you have to close the certificate store
but then you have to be sure that WinInet is no longer active (and
holding a reference to the certificate) because you'll get a crash if
WinInet accesses certain CSP functions if the store has already been closed.

I'll try to do some further debugging.


Danny
---
Back to top
danny heijl
Guest





PostPosted: Mon Apr 02, 2007 2:12 pm    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

danny heijl schreef:

Quote:
I'll try to do some further debugging.

This is the call stack when the CSP crashes (this is when the 2 fields
are not zeroed in the THTTPRIO destructor):

:7c9118c5 ntdll.RtlDeleteCriticalSection + 0x3b
:0276b2ae ; C:\WINDOWS\system32\beidcsp.dll
:7c9011a7 ntdll.LdrInitializeThunk + 0x29
:7c923f31 ; ntdll.dll
:7c81cd76 ; C:\WINDOWS\system32\kernel32.dll
:7c81cdee kernel32.ExitProcess + 0x14
:00404d9d @Halt0 + $C5


When I clear those 2 fields in the THTTPRIO destructor I can't reproduce
this crash.

I'll email the webservice client code.

Danny
---
Back to top
Mikael Eriksson
Guest





PostPosted: Tue Apr 10, 2007 2:30 pm    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

danny heijl skrev:
Quote:
When I clear those 2 fields in the THTTPRIO destructor I can't reproduce
this crash.

I'll email the webservice client code.


Hi!

I followed this thread with some interest but it seams that you have
sorted this out in a more private fashion.
Just wonder if you came to any solution regarding the leak/AV?

regards

/Micke
Back to top
danny heijl
Guest





PostPosted: Tue Apr 10, 2007 11:35 pm    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Mikael Eriksson schreef:

Quote:
I followed this thread with some interest but it seams that you have
sorted this out in a more private fashion.
Just wonder if you came to any solution regarding the leak/AV?

- As Bruneau pointed out: it is not a leak
- I have no idea why these changes made the crash go away
- I suspect the Belgian EID Windows CSP implementation has a problem
with WinInet when an EID certificate is being used as a client
certificate by WinInet. Someone Somewhere is not releasing CSP handles
properly. Other certificates (other CSP's) do not show the problem.

Danny
---
Back to top
Mikael Eriksson
Guest





PostPosted: Tue Apr 10, 2007 11:52 pm    Post subject: Re: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

danny heijl wrote:
Quote:
- I suspect the Belgian EID Windows CSP implementation has a problem
with WinInet when an EID certificate is being used as a client
certificate by WinInet. Someone Somewhere is not releasing CSP handles
properly. Other certificates (other CSP's) do not show the problem.


Thanks. Good to know that I do not need to worry about this at least.

regards

/Micke
Back to top
test
Guest





PostPosted: Fri Apr 13, 2007 7:38 pm    Post subject: RE: D2006 memory leak (and potential AV) in SoapHTTPClient.P Reply with quote

Quote:
There is a memory leak in SoapHTTPClient.pas: the constructor takes a
copy of the interfaced objects FDefaultDomConvertor and FDefaultWebNode
but the destructor does not release the copies of these interfaces.

When using SSL with client certificates (a simple patch in the soap http
transport will enable this) for soap, this can lead to an access
violation in the CSP for the certificate used by Wininet. Because the
interface using WinInet is not freed, the WinInet handles are not freed,
and when the program has terminated, and Windows unloads the DLL's,
WinInet tries to free the certificate context used for the SSL (*after*
the Delphi runtime has done it's cleanup) you get an access violation
because everything else has long gone.

The following change remedies the problem (and the memory leak):


destructor THTTPRIO.Destroy;
begin
if Assigned(FConverter) then
FConverter := nil;
if Assigned(FDOMConverter) then // -- added dh --
FDOMConverter := Nil; //
if Assigned(FWebNode) then
FWebNode := nil;
if Assigned(FHTTPWebNode) then // -- added dh --
FHTTPWebNode := Nil; //
if Assigned(FWSDLView) then
FWSDLView.Free;

{ All components we own are automatically cleaned up }
inherited;
end;

Danny
---

test

BizTalk Utilities - Frustration free BizTalk Adapters
http://www.topxml.com/biztalkutilities
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi WebServices SOAP All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.