Source PDF link: http://www.belldandy.idv.hk/GS/SourceTempFile1030_0222381.pdf Source PDF Producer: Acrobat Distiller 7.0 (Windows) Debug Message:http://www.belldandy.idv.hk/GS/debugMessage.txt Step 1: Use Adobe Reader 8.1.1 read SourceTempFile1030_0222381.pdf, print to PS file. No Error. Step 2: PS file -> PDF by GSWin32c, fail. Debug message: **** DSC comment: /Page << /PageNum 1 /DSC_struct -dsc_data_struct- >> (debug message stop in here)
Created attachment 3507 [details] PS file created by Acrobat 8.1.0 from the sample PDF file
Created attachment 3508 [details] patch Work around a possibility that t_struct ref can be constructed from a NULL pointer. I don't yet know where such ref's are broken and the bug should be fixed elsewhere. Such ref's can be easily found by checking addressability of the pointer in make_struct macro.
This appears to be a pdfwrite issue, so assigning to Ken
When I use ghostscript version 8.61 Step 1: Use Adobe Reader 8.1.1 read SourceTempFile1030_0222381.pdf, print to PS file. No Error. GsView 4.9 can open it. Step 2: PS file -> PDF by GSWin32c, fail. Debug message: **** DSC comment: /Page << /DSC_struct -dsc_data_struct- /PageNum 1 >> (debug message stop in here)
Help ? :-( I'm at a bit of a loss with this one. While it only seems to go wrong with pdfwrite, I can't (at the moment) see why this is the case. Alex's patch works round the problem, but it doesn't address the underlying issue. The job sets up a Pattern with a revolting PaintProc (it draws tiny imagemasks, I think to create a logo). Anyway, the problem exhibits inside the PostScript interpreter. It sets a colour, determines its a pattern colour, installs a capture device (I think) and then exits with an error code which causes GS to run the PaintProc. The problem 'seems' to occur while executing the PaintProc. But it might be something pdfwrite is doing, the PaintProc takes an age to execute in the interpreter and I haven't found a way to isolate the specifics of the problem, whether its the PaintProc causing the problem, or whether pdfwrite is pushing another exec. Does anyone have any hints on how to debug this ?
I believe the bug is wrongly assigned. I'll check with Henry.
Well it does only happen with pdfwrite, so I think its entirely possible (perhaps even likely) that pdfwrite is causing the execstack which fails. My problem is that it takes forever to step through the initial PaintProc execution in the PostScript interpreter. (BTW it seems the pattern is used to draw dashed lines...) I suspect that there's some pattern madness going on in pdfwrite, after the pattern has been captured, but I don't know enough to put a sensible breakpoint in place. Any clues would be much appreciated ;-)
I don't know if this helps, and I apologize in advance if you already knew all of this and it's way to basic. --- You can turn on interpreter tracing, or other -Z debug actions from within PostScript using .setdebug so you don't need to have -ZI on the whole time. For example, to turn on interpreter tracing, use: (I) true .setdebug and to turn it off later, (I) false .setdebug I also sometime through in a "() false .setdebug" in PS to allow me to hit a breakpoint in zsetdebug. The normal (not big pattern approach) is to run the PaintProc after setting a 'pattern accumulator' device (see src/gxpcmap.c:gx_pattern_accum_alloc). The PaintProc is actually 'run' from zpcolor.c:pattern_paint_prepare which "pushes" the PaintProc on to the execstack (near the end). It also pushes the 'closure' "pattern_paint_finish" that does the cleanup. Thus, you should see the pattern_paint_prepare followed by pattern_paint_finish when the PaintProc finishes. Igor can explain the big_pattern (currently bitmaps > 1Mb) logic, but basically it installs a 'clist device' as the pattern accumulator. The pdfwrite device modifies this quite a bit because it supports it's own 'pattern_manage__*' functions. Since the problem is specific to pdfwrite, looking through the src/gdevpdfi.c and associated logic is needed. Once again, Igor would be the one to explain this.
Regarding comment #8 : When developing big patterns, I did not do anything special to pdfwrite. The latter implements its own pattern stream accumulator. The clist-based accummulator must not run with pdfwrite.
regarding Cpomment #2 : First need to figure out whether NULL struct pointer must be a legal case or not. If yes, it's Alex's job, since he owns zcontrol.c .
Thanks for the hints everyone. The problem appears to be caused by the fact that the pattern paints an image, and the image is in a CIEBasedABC colour space. If I alter the image dictionary (in the pattern PaintProc) to use DeviceRGB instead, the problem disappears. Since the image is in fact monochrome, this gives the correct result. So now I have to find out what pdfwrite is doing wrong to create an empty frame when evaluating a CIEBased colour space in a Pattern context. Might take a while but I have a starting point. Thanks again.
Created attachment 3681 [details] Minimal file to reproduce the problem I believe I now fully understand this issue, and its not specifically related to pdfwrite. As a result I'm assigning it to Alex for a final decision on what to do. The following detailed explanation is intended for Alex, and anyone else interested :-) The issue is to do with devices handling patterns as high-level objects, which is why it affects pdfwrite (which can handle patterns itself) but not regular rendering. In zpcolor.c, pattern_paint_prepare(), there are two control paths, one for devices which handle patterns as high-level objects, and one for devices which don't. If the device can't handle high level objects, we install a pattern accumulation device. In this case, the flag internal_accum is set, we create the pattern accumulator device and open it: if (internal_accum) { gs_memory_t *storage_memory = gstate_pattern_cache(pgs)->memory; pdev = gx_pattern_accum_alloc(imemory, storage_memory, pinst, "pattern_paint_prepare"); if (pdev == 0) return_error(e_VMerror); code = (*dev_proc(pdev, open_device)) ((gx_device *) pdev); ... ... } Later the two control paths rejoin and we put some objects on the execution stack: push_mark_estack(es_other, pattern_paint_cleanup); ++esp; make_istruct(esp, 0, pdev); Now notice that we construct the structure on esp using pdev, but we *don't* create pdev if we can handle patterns, so its left as NULL and we end up pushing an empty t_struct. Leo's question in comment 10 is whether this is legal, the answer appears to be yes, but its debatable. In pattern_paint_finish we do this: gx_device_forward *pdev = r_ptr(esp - 1, gx_device_forward); if (pdev != NULL) { gx_color_tile *ctile; int code = gx_pattern_cache_add_entry((gs_imager_state *)igs, pdev, &ctile); That is, if the structure *isn't* NULL we do something with it, we ignore it if it is NULL. Either way we then do this: esp -= 3; Removing all the objects from the execution stack that we added. Notice that the structure we pushed onto the execution stack isn't actually 'executed', its just data used by the pattern handler. Now, all this works just fine in normal practice, however the job here uses a CIEBased colour space, and being from an Adobe application it tries to set the ColorRendering. Since we don't implement a ColorRendering resource category, this causes an error (handled in a stopped context). The default error handler uses execstack, and this is where the actual error finally occurs, because execstack can't handle the empty structure. I have no idea how common the practice of putting device structures on the execution stack is, so I can't judge whether this is expected behaviour. If it is we should adopt Alex's initial patch and modify execstack & friends to handle the situation. Otherwise we should adopt whatever is the 'correct' method for dealing with this kind of argument passing and modify the pattern handling code appropriately. My guess is that we should just modify the execstack stuff. For ease of further investigation I've attached a much simplified job, the PaintProc for the pattern has a single line which is commented out. Remove the comment and run with a device capable of high-level pattern handling to generate the error.
*** Bug 689809 has been marked as a duplicate of this bug. ***
The patch from the comment #2 is committed as a rev. 8901. Even if NULL pointers to structures are invalid, a crash in execstack is clearly undesirable. This patch is similar to a protection measure in modern printf(), which prints NULL instead of crashing when it receives NULL pointer. Besides, NULL is a valid pointer value in C and it should be possible to pass it through PostScript level and expect that it is compatible with the error handler.
*** Bug 689992 has been marked as a duplicate of this bug. ***