| Summary: | procedure data target not always closed | ||
|---|---|---|---|
| Product: | Ghostscript | Reporter: | Chapman Flack <ghost> |
| Component: | PS Interpreter | Assignee: | Ray Johnston <ray.johnston> |
| Status: | NOTIFIED FIXED | ||
| Severity: | major | ||
| Priority: | P3 | ||
| Version: | 8.51 | ||
| Hardware: | PC | ||
| OS: | NetBSD | ||
| Customer: | Word Size: | --- | |
Weird: in CVS diffs for zfproc.c, I don't see anything between 7.07 and 8.51 that looks like it could account for this - but I definitely never saw the problem before upgrading, and now it's entirely repeatable. Performing regression test (on Genoa test suite) with the patch:
***************
*** 279,285 ****
stream_proc_state *const ss = (stream_proc_state *) st;
uint rcount = pr->limit - pr->ptr;
! if (rcount > 0) {
uint wcount = r_size(&ss->data) - ss->index;
uint count = min(rcount, wcount);
--- 279,286 ----
stream_proc_state *const ss = (stream_proc_state *) st;
uint rcount = pr->limit - pr->ptr;
! /* if 'last' return CALLC even when rcount == 0. ss->eof terminates */
! if (rcount > 0 || (last && !ss->eof)) {
uint wcount = r_size(&ss->data) - ss->index;
uint count = min(rcount, wcount);
-----------------------------------------------------------------------------
This definitely results in the 'false' call, producing:
true()
true(H)
true(i)
false()
and *should* be OK for other proc_write usage. As the PLRM states,
Encode filters are fairly rare, and procedure targets are a subset
of those. I will examine the Genoa tests to see which, if any, of
them tests this case. If no problems, I will commit.
Patch committed. Testing showed no problems. |
When a procedure is a data target, it is signalled that it has been closed by one final callback with a possibly empty string containing any final buffered data, and the boolean false. GS 8.51 does not seem to do this unless the buffer is nonempty at time of closefile: AFPL Ghostscript 8.51 (2005-04-18) Copyright (C) 2005 artofcode LLC, Benicia, CA. All rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for details. GS>{ =only == ( ) } /NullEncode filter dup (Hi) writestring closefile true() true(H) false(i) % good, but: GS>{ =only == ( ) } /NullEncode filter dup (Hi) writestring GS<1>dup flushfile closefile true() true(H) true(i) GS> % whoa, where's the close? and even: GS>{ =only == ( ) } /NullEncode filter closefile GS> % whoa, where's the close? By contrast: PostScript(r) Version 3010.108 (c) Copyright 1984-1999 Adobe Systems Incorporated. Typefaces (c) Copyright 1981 Linotype-Hell AG and/or its subsidiaries. All Rights Reserved. PS>{ =print == ( ) } /NullEncode filter dup (Hi) writestring dup flushfile true() true(H) true(i) PS>closefile false() % good, gets closed PS>{ =print == ( ) } /NullEncode filter closefile false() % good, gets closed Not sure when this changed; my code that relies on procedure data targets worked in GS 7.07, but 8.51 is definitely broken. The bug means a data target procedure that needs to take special action on close fails badly.