cancel
Showing results for 
Search instead for 
Did you mean: 

memory leak with windows service

Former Member
0 Kudos

Hi,

comparable to description of , I still do have the same problem.

The application runs as a windows service on Windows Server 2012.

I'm using Crystal Report v13.0.13 for .NET (x64 , Framework 4.5.2) with visual studio 2013.

Accourding to the "Fixed issues" at http://scn.sap.com/docs/DOC-7824 this problem has not been fixed in th newer releases.

The problem exits since we migrated the project from 32-bit to 64-bit and from VS 2008 to VS2013.

It is definitly Crystal R. that does not free the memory correctly.

Which further informations do you need to fix this bug?

Thanks in advance!

Accepted Solutions (1)

Accepted Solutions (1)

DellSC
Active Contributor
0 Kudos

The thing to remember is that the Crystal and BO SDKs are based on COM objects, which can cause memory leaks if not handled correctly.  So, when possible, you should either enclose calls to a report in the SDK with a "using" clause, or explicitly call .dispose() on the report when you're done with it.

-Dell

Former Member
0 Kudos

Thank you for your fast response. Unfortunately that's what I am already doing: .Dispose() on the Crystal R.-object and additionally on the DataSet and tables.

{

    [...]

        try
        {
            [...]
            crReportDocument = new ReportDocument();
            crReportDocument.Load(pathReport);
            crReportDocument.SetDataSource(dsData);
            crReportDocument.PrintOptions.PaperOrientation = CrystalDecisions.Shared.PaperOrientation.Landscape;
            crReportDocument.SetParameterValue("finalized", false);

            if (myDestination.Equals(DestinationChoice.toDisk))
            {
                crReportDocument.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, fileWithPath);
            }
            else if (myDestination.Equals(DestinationChoice.toHttpResponse))
            {
                crReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, System.Web.HttpContext.Current.Response, true, filename);
            }
        }
        catch (Exception ex)
        {
            throw ex.ToString();
        }
        finally
        {
            if (crReportDocument != null)
            {
                crReportDocument.Close();
                crReportDocument.Dispose();
            }
            tabMaindata.Clear();
            tabMaindata.Dispose();
            tabSubrpdata.Clear();
            tabSubrpdata.Dispose();
            dsData.Clear(); //DataSet contains tabMaindata and tabSubrpdata
            dsData.Dispose();
        }
    }

Answers (2)

Answers (2)

Former Member
0 Kudos

There are changes due to Crystal Report v13.0.17 for .NET.

The memory leak is still present, but smaller.

Summary of this thread:

* I am using the Release-build and the latest CR-version for .Net.

* I am releasing the CR-objects correctly (same results with using() and explicit dispose()).

* I am using all the suggested GC.Collect()-calls.

* The test-reports are prepared according to Dons suggestions.

Unfortunately that all has not improved anything.

SOLVED:

* The mentioned website-problems have been fixed in v13.0.17 (files in temp-folder) / solved by a workaround as described in this thread ("ThreadAbortException").

STILL AN ISSUE:

* Memory leak in windows service:

System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 138035200

System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 101011456

<...creating 500 pdfs...>

System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 148779008

System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 107872256

Memory consumption is growing meanwhile

about +10 MByte (initial: +12 MByte) for WorkingSet64, and

about +6 MByte (initial +13 MByte) for PrivateMemorySize64

per 500 created PDFs.

Do you need more infos/which further actions could I do?

Greetings

C. Lo

former_member183750
Active Contributor
0 Kudos

How do you know there is a memory leak? E.g.; errors? symptoms? behavior? What tool do you use the track the memory usage?

How do you know it is CR that is leaking?

- Ludek

Senior Support Engineer Product Support, Global Support Center Canada

Follow me on Twitter

Got Enhancement ideas? Use the SAP Idea Place

Former Member
0 Kudos

Hi Ludek,

the sourcecode is posted above, .Dispose() is in use.

For examination, we reduced the code and simulated all steps of the complete process during PDF-generation. Memory consumption was normal for each step, except when calling the crReportDocument.ExportToDisk() line. We logged the value returned by calling Process.GetCurrentProcess().WorkingSet64.ToString() for checking the memory.

After generating 25000 PDFs (within one run), the windows service requires over 420 MByte RAM, about 35 MByte would be normal. Calling garbage collection does not help:

GC.Collect(0, GCCollectionMode.Forced);

GC.Collect(1, GCCollectionMode.Forced);

GC.Collect(2, GCCollectionMode.Forced);

Thank you very much!

0 Kudos

OK, but that doesn't show the dependencies being used, just the whole process.

Did you run in debug mode or Release mode? There are differences between the VS debug dll's and Release dll's.

Monitor the \temp folder and see if the files are being cleaned up. You may have to wait, Windows can take time, wait until the app is idle to see if they go away. And when closed do they get deleted?

Run Perfmon and watch the private byes on a release build of your app..

Are you using a report with saved data so it removed the DB client from the picture? Or even better just add a text object to the report with "Hello World" in it and run that report and select No Printer in the Page Setup, that removes the printer driver from the picture and relies on GDIPlus to format the page.

Also, when calling GC.Collect you need to add a few more lines:

GC.Collect();

GC.WaitForPendingFinalizers();

GC.Collect();

Not all fixes will be listed in the readme file and any previous fixes automatically get rolled forward.

Don

Former Member
0 Kudos

Hi Don,

> Did you run in debug mode or Release mode? There are differences between the VS debug dll's and Release dll's.

Thank's for the hint, for project "A" we are using the debug-build only (a DLL for a windows service (issue: non-freeing memory) and for a website (issue: remaining temp-files).

Webproject "B" uses a 100% release-build with the same issue (remaining temp-files).

In the following I am checking your suggestions with both projects in release-mode.

Summary of tests: nothing changed, no break through. Maybe the exception-hint of the webproject at the end of this text is useful.

> Monitor the \temp folder and see if the files are being cleaned up.

> You may have to wait, Windows can take time, wait until the app is idle to see if they go away. And when closed do they get deleted?

Regarding webproject "B":

Partually. *.tmp-files remain (e.g. "tmp8DB6.tmp"). _That_ are the problem files.

> Run Perfmon and watch the private byes on a release build of your app..

webproject "B", before calling crReportDocument.ExportToHttpResponse(), 1. turn:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    234700800

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    208293888

2. turn:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    214327296

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    183783424

3.:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    200982528

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    169848832

4.:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    196390912

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    165408768

5.:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    194387968

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    163135488

6.:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64    194822144

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64    163696640

No growing memory consumption of the webpage.

project "A", Windows service:

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64     136384512

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64     96813056

<...creating 500 pdfs...>

    System.Diagnostics.Process.GetCurrentProcess().WorkingSet64     148004864

    System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64     110403584

Unreleased memory.

> Are you using a report with saved data so it removed the DB client from the picture?

> Or even better just add a text object to the report with "Hello World" in it and run that report and select No Printer in the Page Setup,

> that removes the printer driver from the picture and relies on GDIPlus to format the page.

That's what I did for testing:

1. logoff from any db connection

2. removing all picture objects (embedded and such ones set per formula)

3. Page Setup: No Printer

4. default config: don't save preview picture + already set: remove saved data (in english something like "skip saved data on loading")

5. Database: don't check with each printing

Does not help, nothing changed (both projects).

>Also, when calling GC.Collect you need to add a few more lines:

>> GC.Collect();

>> GC.WaitForPendingFinalizers();

>> GC.Collect();

Done. In addition I've added: Calling .Close() and .Dispose() on all SubReports.

Does not help (both projects).

> Not all fixes will be listed in the readme file and any previous fixes automatically get rolled forward.

Okay, thanks for that detail. I've updated to latest version 13.0.16 ("CRforVS_13_0_16.exe").

Still unreleased memory (in same dimension) / files like "tmp8DB6.tmp" remain in Windows temp-folder.

Does not help (both projects).

Greetings

C. Lo

Hints:

1. I have checked all above while running the project within Visual Studio 2013.

2. Regarding webproject "B":

In debug-mode I am getting this exception after calling .ExportToHttpResponse().

Nevertheless, after the exception (and after all the .Close()-calls, var. set to null etc.) the pdf is ready for download - and complete.

The exception contains this [translated], followed by the stack trace below:

"Der Ausdruck konnte..." = "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above."

"Der Thread wurde abgebrochen." = "Thread aborted."

-        ex    {"The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.}    System.Exception {System.Threading.ThreadAbortException}

+        [System.Threading.ThreadAbortException]    {"The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.}    System.Threading.ThreadAbortException

        _className    null    string

        _data    null    System.Collections.IDictionary

        _dynamicMethods    null    object

        _exceptionMethod    null    System.Reflection.MethodBase

        _exceptionMethodString    null    string

        _helpURL    null    string

        _HResult    -2146233040    int

+        _innerException    null    System.Exception

+        _ipForWatsonBuckets    8791379550089    System.UIntPtr

        _message    "Thread has been aborted."    string

        _remoteStackIndex    0    int

        _remoteStackTraceString    null    string

+        _safeSerializationManager    {System.Runtime.Serialization.SafeSerializationManager}    System.Runtime.Serialization.SafeSerializationManager

        _source    null    string

+        _stackTrace    {sbyte[384]}    object {sbyte[]}

        _stackTraceString    null    string

        _watsonBuckets    null    object

        _xcode    -532462766    int

+        _xptrs    0    System.IntPtr

        Data    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    System.Collections.IDictionary

        HelpLink    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    string

        HResult    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    int

        InnerException    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    System.Exception

        IPForWatsonBuckets    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    System.UIntPtr

        IsTransient    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    bool

        Message    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    string

        RemoteStackTrace    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    string

        Source    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    string

        StackTrace    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    string

        TargetSite    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    System.Reflection.MethodBase

        WatsonBuckets    "The expression could not be evaluated because the code has been optimized or in the call stack a native frame is included above.    object

Stack trace (first lines are the latest):

     mscorlib.dll!System.Threading.Thread.Abort(object stateInfo = {unknown})    C#

     System.Web.dll!System.Web.HttpResponse.AbortCurrentThread()    C#

     CrystalDecisions.Shared.dll!CrystalDecisions.Shared.SharedUtils.WriteToResponse(System.Web.HttpResponse response = {unknown}, System.IO.Stream inputStream = {unknown}, bool exclusive = {unknown})    C#

     CrystalDecisions.CrystalReports.Engine.dll!CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportOptions options = {unknown}, System.Web.HttpResponse response = {unknown}, bool asAttachment = {unknown}, string attachmentName = {unknown})    C#

     CrystalDecisions.CrystalReports.Engine.dll!CrystalDecisions.CrystalReports.Engine.ReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportFormatType formatType = {unknown}, System.Web.HttpResponse response = {unknown}, bool asAttachment = {unknown}, string attachmentName = {unknown})    C#

    my_Website.dll!my_Website.presentation.my_Page.btn_Print_Click(object sender = {unknown}, System.EventArgs e = {unknown})    C#

(end of text)

Former Member
0 Kudos

I've implemented the suggestion of Dell Stinett-Christy, calling the export with a "using" clause

(without and with trying to clean the ReportDocument via .Close&.Dispose in an additional catch()-routine).

Still unreleased memory (in same dimension) / files like "tmp8DB6.tmp" remain in Windows temp-folder.

     System.Diagnostics.Process.GetCurrentProcess().WorkingSet64      135520256

     System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64      96231424

<...creating 500 pdfs...>

     System.Diagnostics.Process.GetCurrentProcess().WorkingSet64      146440192

     System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64      102490112

Does not help (both projects).

Is the following of interest?


project "A" (windows service) uses these Crystal-references:

webproject "B" uses these Crystal-references:

0 Kudos

If you stop the service does it clean up those temp files?

When our engine finishes with a report it should close and delete all temp files we ask the OS to create. Or at least mark them as can be deleted. Sometimes the Hardware is slow to respond to the request.

How about permissions? CR requires full read/write to the System temp folder so it can export. When exporting it first tries to write the file and then delete it to see if the process has full rights. If not it can leave behind files.

Possibly Firewall and/or AV software is blocking access....

Don

Former Member
0 Kudos

Hi Don,

you are right, but: yes and yes. That's why & how our workaround works:

project "A" (windows service) - the service restarts programmaticaly, when it is consuming more than x-hundred MBytes of RAM. After that, complete memory is released.

webproject "B" - the webpage is deleting all *.tmp-files (older than xy) from the windows temp-folder, when doing something regarding pdf-creation. (Before that, we were running into the ">32k files in win-temp-folder-problem".)

> Possibly Firewall and/or AV software is blocking access

Nope, same behaviour on DEV-machine as on productive environment.

Greetings

C. Lo

0 Kudos

Hi C,

That would be normal, as the project loads CR runtime it will typically grow to 100 meg, and this is known and confirmed by DEV. So when running stress tests etc. it is typical for the app to consume that much memory.

I had some of those TMP*.tmp files also but they were not owned by CR. I closed all CR app's and designers, deleted all file int he temp folder which were not locked and ran my WEB app in both IISExpress ( debug mode ) and using IIS on my Windows 10 image and I did not see any of those TMP files being generated.

I did see a lot of ~cre*.tmp file created and a few that started with D.... but they were deleted after I changed IIS from 32 to 64 bit mode. Both modes created the same number of files and none were TMP*.tmp files.

I did some more testing and closed VS and ran the test app from IIS and I don't see any temp files being created in the User \temp folder.

I'll do more testing and see if I can figure this out....

Don

0 Kudos

One thing I never asked, are you using Sessions to keep the report in scope and PostBack so when the report is closed it tells the engine to delete the files?

Former Member
0 Kudos

Hi Don,

> If you stop the service does it clean up those temp files?

The service has no remaining temp files. The webproject does not clean up the mentioned temp-files.

Regarding webproject "B":

yes, we are using sessions for the website (no cookies).

Looking at the history of this thread - shall I prepare a VS-project with our *.RPT for debugging that on your own?

It is no CR-migration-problem (update from CR-vXY), because it the same with a newly created RPT (with VS 2013).

UPDATE June-2: There is no difference between using IIS Server / ISS Express (except of the temp-folder located in the user-dir. \AppData\Local\Temp).

UPDATE June-11: At least this is fixed now: "C. Lo May 11, 2016 2:59 PM", exception without useful content while calling CR-method. It is a System.Threading.ThreadAbortException error.

-> Instead of calling crystals ExportToHttpResponse()-method, this works as mentioned in , from the year 2011 (my implementation differs a bit):

Stream crstream = crReportDocument.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);//, System.Web.HttpContext.Current.Response, true, fileName);

Response.ContentType = "application/pdf";

Response.AddHeader("content-disposition", "attachment;    filename=\"" + fileName + ".pdf\"");

byte[] buffer = new byte[4096];

int count = 0;

while ((count = crstream.Read(buffer, 0, buffer.Length)) > 0) //this provides a correct value in HTML headerfield "Content-Length"

{

    Response.OutputStream.Write(buffer, 0, count);

    Response.Flush();

}

HttpContext.Current.ApplicationInstance.CompleteRequest();

//Response.End(); <--this line produces a similar error like ExportToHttpResponse() -> "ThreadAbortException: Thread has been aborted."

Meanwhile any further hints or ideas?

Greetings

C. Lo

Message was edited by: C. Lo: solution added for System.Threading.ThreadAbortException