NETMF / netmf-interpreter

.NET Micro Framework Interpreter
http://netmf.github.io/netmf-interpreter/
Other
487 stars 224 forks source link

[NETMF4.3.1] Memory leak while using “POST” method by HTTPS. #480

Open Yuri-N opened 8 years ago

Yuri-N commented 8 years ago

I am facing the memory leak while using “POST” method by HTTPS.

I put below code to every after throwing “POST” in order to make sure the heap memory condition. Debug.GC(true).ToString();

Here is the result.

I got exception. It seems not to have enough memory for BINARY_BLOB_HEAD.

#### Exception System.Net.Sockets.SocketException - CLR_E_FAIL (1) ####
#### Message:
#### Microsoft.SPOT.Net.Security.SslNative::SecureConnect [IP: 0000] ####
#### Microsoft.SPOT.Net.Security.SslStream::Authenticate [IP: 0060] ####
#### Microsoft.SPOT.Net.Security.SslStream::AuthenticateAsClient [IP: 000c] ####
#### System.Net.HttpWebRequest::EstablishConnection [IP: 0247] ####
#### System.Net.HttpWebRequest::SubmitRequest [IP: 0019] ####
#### System.Net.HttpWebRequest::GetRequestStream [IP: 0008] ####

In this time, program does not run properly because of memory shortage.

  [Temporary solution] It seems that EstablishConnection() in System.Net.HttpWebRequest.cs causes memory leak. Actually, EstablishConnection() is called by every time when “POST” is proceeded. This is why memory leaks with every “POST” throwing. I temporary changed code as below. File: System.Net.HttpWebResponse.cs Function name: protected override void Dispose(bool disposing)

--- original code // If server had not send this header or value is not "close", then we keep connection. closeConnection = connValue == null || connValue.ToLower() == HttpKnownHeaderValues.close;

--- Modified code

// If server had not send this header or value is not "close", then we keep connection.
//closeConnection = connValue == null || connValue.ToLower() == HttpKnownHeaderValues.close;

if (connValue == null) closeConnection = false;                                                     
else if(connValue.ToLower() == HttpKnownHeaderValues.close) closeConnection = true;              
else closeConnection = false;                                                                    

This modification is related with what to dispose after receiving reply from server.

I am not sure if this modification is acceptable, or right way to fix it. At least, it is working very well in my end.

smaillet-ms commented 8 years ago

Unless my pre-caffeinated brain is missing something... that can be reduced to a simpler expression:

closeConnection = connValue.ToLower() == HttpKnownHeaderValues.close;

Since only one condition leads to setting closeConnection to true that makes for a simpler form

Yuri-N commented 8 years ago

Dear smaillet-ms,

Thanks for advice! I will try it.

Unfortunately, this solution works only during Keep-alive state. Once "Keep-alive" expires, need to connect to server by EstablisheConnection(). It makes memory leak again. For example,, To connect to the server which has Keep-alive max is 100, the memory leak occurs every 100 POST messages.

In my feeling, HttpWebRequest.AllowWriteStreamBuffering should be "false" but NETMF4.3.1 does not support it.

So... need to find out the root cause of memory leak. maybe during buffering BLOB. But it is too difficult for me... If you help me to solve it, I would appreciate very very much.

Best Regards, Yuri

smaillet-ms commented 8 years ago

The actual leak is likely the same one identified in #160. At present we don't have any idea where the actual leak is (It seems to be deep in the OpenSSL stack or the NETMF wrappers around it but the leak has proven to be very illusive and difficult o identify)