Bug 692372 - Handle leakage when using GS9.00
Summary: Handle leakage when using GS9.00
Status: NOTIFIED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: General (show other bugs)
Version: 9.00
Hardware: PC All
: P2 normal
Assignee: Ray Johnston
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-07-25 06:29 UTC by Marcos H. Woehrmann
Modified: 2011-11-25 04:10 UTC (History)
0 users

See Also:
Customer: 580
Word Size: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marcos H. Woehrmann 2011-07-25 06:29:43 UTC
The customer reports:

I noticed there is handle leakage when using GS9.00
I’m using all in one dll (10 MB dll), where there are no run time files (i.e. the same dll you’re using with demos)
 
I’m attaching a demo that show the problem
 
I did the following, I put some random arguments in the project settings at “Command Arguments”
 
As following all of these has nothing to do (feel free to change it)
-dNOPAUSE -dBATCH -sPDFPassword=111 -dCompatibilityLevel=1.6 -sDEVICE=pdfwrite  -sOwnerPassword= -dEncryptionR=3 -dKeyLength=128 -dPermissions=1024 -sOutputFile=c:\dec15.pdf c:\1.pdf
 
Then I called
 
For  loop 300 times
{
gsapi_new_instance
gsapi_init_with_args
gsapi_exit
gsapi_delete_instance
}
 
You can notice that the number of handles increased rapidly (you make another loop with 300times and you will notice that the number of handles is doubled).
The leakage for 300 was about 700 handles
 
To reproduce please do the following:
 
-    Download Process Explorer:
http://technet.microsoft.com/en-us/sysinternals/bb896653
 
-    Right click the “exe application” (e.g. the demo I sent) select properties and see the number of handles.
 
Check the screenshot below and see the number of handles.
Comment 1 Marcos H. Woehrmann 2011-07-25 06:30:46 UTC
Created attachment 7712 [details]
screenshot.png
Comment 3 Ken Sharp 2011-07-25 06:50:57 UTC
Does this only occur with pdfwrite, or is there some other reason this is assigned to me ?
Comment 4 Ken Sharp 2011-07-25 10:59:08 UTC
With no arguments at all (just invoke gswin32), I see the handles increase by ~ 2 per loop iteration. Which is broadly in line with what the customer reports.

The first of these is related to the ICC cache, it is allocated in 'gsicc_cache_new':

    result->wait = gx_semaphore_alloc(memory->stable_memory);

Each time we start up the interpreter we execute this code, which results in a handle being used, which is never freed.

The other I haven't been able to track down yet, as it happens during gs_interpret():

    code = gs_call_interp(pi_ctx_p, pref, user_errors, pexit_code,
                          perror_object);

This one is going to be much more difficult to track down, it also doesn't seem to occur on every loop iteration, but that might be caused by the asynchronous nature of running an external application to monitor the handles. It just may not be updating fast enough.

I'm reassigning this to Ray for now, as I *think* the semaphore stuff was his. If not maybe it should go to Michael, I'm uncertain. I have no idea who gets the task of figuring out where the other handle leaks from.
Comment 5 Ray Johnston 2011-07-26 16:12:42 UTC
The gsicc_cache.c is freeing the monitor and semaphore memory without closing
them. The proper use is to call gx_semaphore_free and gx_monitor_free.

I have traced the handle count during a 'debug' gswin32c session.

The initial handle count assigned to the process is 46, then loading the dll
increases the count to 55. Tracing through, the handle count doesn't change
as a result of the InitializeCriticalSection call, and the handle value returned
doesn't show up on Microsoft's Process Explorer. Furthermore unloading the
DLL only frees up 7 handles instead of 9.

This is going to be difficult to track without reliable tools.
Comment 6 Ken Sharp 2011-07-27 08:53:29 UTC
Rays' change for the sempahores, which I accidentally committed as 'cb048fc7c5fdfe82550b8f0a80de2ff5fd64739f' solves this problem for me.

Using Process Explorer I no longer see the handle count increase by two per loop iteration, the handle count is stable from beginning to end of the execution.

Process Explorer is not the ideal tool for this investigation. The handles shown in its dialog are *not* specific to the process but are the number of handles open by the entire system. As such they can change unpredictably (and hence our confusion over the handle count). Robin pointed me to Sys Internals' handle.exe application which does a much better job (it is, however, a command line application, no GUI).

Since this is assigned to Ray I'm going to leave it to him to close the issue, but this now works as expected for me.
Comment 7 Ray Johnston 2011-07-27 17:15:44 UTC
Thanks for testing, Ken. Just for reference, I don't mind if someone closes
bugs assigned to me. There are plenty of others ;-)
Comment 8 Ken Sharp 2011-08-12 08:30:09 UTC
While Ghostscript no longer leaks handles simply by starting and stopping (ie the sequence gsapi_new_instance/gsapi_init_with_args/gsapi_exit/gsapi_delete_instance) it does leak 3 semaphores per loop *if* we actually execute a job. I tried several command lines, the simplest is something like '-sDEVICE=tiff24nc -r72 -o out.tif /gs/examples/tiger.eps'

I 'suspect' that this is something device related, but I'm unsure what it might be. I will look later but this may have to wait for Ray to investigate further.
Comment 9 Ken Sharp 2011-08-12 14:55:49 UTC
I'm afraid this one is beyond me. The routine 'rc_gsicc_link_cache_free' is never called, which is why the semaphores are not released. I suspect this is a reference counting problem, but am not sufficiently clued in to this area of the code to make much sense of it.

This really needs either Michael or Ray to look at it. Since Ray is unavailable at the moment I will continue to poke, but without much hope of success.
Comment 10 Ken Sharp 2011-08-15 11:57:30 UTC
(In reply to comment #9)
> I'm afraid this one is beyond me. The routine 'rc_gsicc_link_cache_free' is
> never called, which is why the semaphores are not released. I suspect this is a
> reference counting problem, but am not sufficiently clued in to this area of
> the code to make much sense of it.

I'm going to bow out of this now. I don't understand the link cache well enough to know what to do here.

The semaphores are allocated in gsicc_alloc_link, I assumed that when the reference count of the link reached zero the semaphore would be freed, but in fact they are not. The links remain in the cache with a reference count of zero and can be later re-used. Presumably this is nice and efficient, but I can't see any way for the semaphores to be released, gsapi_exit doesn't do it and nor does gsapi_delete_instance.

This needs someone (probably Michael) who understands the bigger picture to fix it. I'm going to change the assignment to Michael, just because I think he's best placed to know what to do and how this is all supposed to hang together.
Comment 11 Michael Vrhel 2011-08-16 01:23:14 UTC
Member variables of the graphic state have a reference count of 3 when we are all done with the file.  Running tiger.eps and putting a break point at line 451 in interp.c in the function gs_interpret you can see that the icc_link_cache, icc_manager, halftone, black_generation, undercolor_removal, basically all reference counted objects of the graphic state are never decremented to zero and so are never freed.  For the link cache this is an issue since the semaphores for the links are not released leaving us with the leaking handles.  

How the graphic state is cleaned up at this point in the code is not clear to me since I am *guessing* that if we are running as a JOBSERVER or with multiple files there is some issue with cleaning up all these objects.  

I am hoping that Ray may have some comments to add about this.
Comment 12 Michael Vrhel 2011-08-17 20:45:49 UTC
reassigning to Henry to have a look.

Run tiger.eps with ppmraw and put a breakpoint in imainarg.c at line 222.
Look at minst->i_ctx_p->pgs.  Several of the member variables including the halftone, black generation, undercolor removal, icc_manager, link_cache have not been deallocated and as far as I can tell the graphic state itself is not really properly freed.   That may be OK for most of these objects since we are shutting down anyway.  The exception would be the link cache which has the handles from the semaphores.  This really needs a specialized clean up.  Which is has if its ref count gets to zero.
Comment 13 Ray Johnston 2011-08-19 00:33:23 UTC
I've made a change to add a finalize to the graphics state / imager state so
that the icc_link_cache gets properly rc decremented. Clusterpush in progress
and I am looking at handle leakage now. The change definitely decerements the
icc_link_cache to zero and frees it, so I expect that the handle leakage will
be resolved.
Comment 14 Ken Sharp 2011-08-25 09:36:31 UTC
(In reply to comment #13)
> I've made a change to add a finalize to the graphics state / imager state so
> that the icc_link_cache gets properly rc decremented. Clusterpush in progress
> and I am looking at handle leakage now. The change definitely decerements the
> icc_link_cache to zero and frees it, so I expect that the handle leakage will
> be resolved.

Ray, I haven't seen a commit for this, did a problem show up with your patch ?
Comment 15 Ray Johnston 2011-08-28 23:15:07 UTC
The 'dev_ht' pointed to by the imager_state apparently is NOT properly
reference counted because the patch to use a 'finalize' procedure to hook
to gs_imager_state_release caused the dev_ht to be freed when it was still in
use.

A hack to 'retain' the dev_ht during gs_imager_state_finalize gets past this,
and even with -Z@$? doesn't result in rc related errors (once a fix was made
to rc_gsicc_profile_cache_free to make sure that curr->net wasn't refrerenced
after curr was freed.

However, currently the clusterpush is giving too many timeouts, which I need
to investigate.
Comment 16 Ray Johnston 2011-09-28 17:49:28 UTC
I added a 'finalize' function to the imager_state so that we can properly
decrement the ref_count of the icc structures (some of which contain semaphores,
and thus use semaphore handles on Windows). Also I fixed the
rc_gsicc_profile_cache_free function to prevent using the forward link (next)
from an element after it was freed.

commit fe8d7b6aebfed3c724a860e31ff170764d5429dc

Should be fixed now, but I've had trouble seeing the handle leakage for some
reason.
Comment 17 Ken Sharp 2011-09-29 07:07:52 UTC
(In reply to comment #16)

> Should be fixed now, but I've had trouble seeing the handle leakage for some
> reason.

I'll try and check it on my system today.