0
votes

I am supporting a ColdFusion 8 website running on Windows Server 2003 R2 (with all Windows Security Updates applied). The website functions smoothly 99.9% of the time. However, about 2 months ago, the ColdFusion 8 Application Server service started crashing and restarting itself every night at 10:30 PM. There is a ColdFusion Scheduled Task that runs at 10:30 PM every night, so I tried running it manually (direct URL in a browser), and sure enough the ColdFusion 8 Application Server service crashed and restarted. So, it's obviously this one template that is causing this to happen.

What this template does is read a directory full of PDF files, then loop through those files to create several thumbnail images for each using CFPDF. This Scheduled Task has been running for years without this issue. The CF service appears to be crashing/restarting almost immediately, before a single file is processed.

I tried running the same template in our Staging environment, and it ran fine - no CF restart. I'm very confused.

Searched through the ColdFusion logs and found nothing.

UPDATE:

Code sample:

<cffunction name="createThumbnails" returntype="Void" output="false">
    <cfargument name="sourcePath" type="String" default="" />
    <cfargument name="overwriteExisting" type="Boolean" default="true" />
    <cfargument name="deleteSourceFile" type="Boolean" default="false" />

    <cfset var _image = {} />

    <cfif FileExists(ARGUMENTS.sourcePath)>
        <cfif   ARGUMENTS.overwriteExisting
            OR  NOT FileExists(getXLargeThumbnailPath())>
            <!---   Large Image for MACXpress --->
            <cfset _image =
                REQUEST.UDFLib.Image.scale(
                    imagePath = ARGUMENTS.sourcePath,
                    maxHeight = 777,
                    maxWidth = 627
                    ) />

            <cfimage
                action="write"
                source="#_image#"
                overwrite="true"
                destination="#getXLargeThumbnailPath()#" />
        </cfif>

        <cfif   ARGUMENTS.overwriteExisting
            OR  NOT FileExists(getXLargeThumbnailPath())>
            <cfset _image =
                REQUEST.UDFLib.Image.scale(
                    imagePath = ARGUMENTS.sourcePath,
                    maxHeight = 211,
                    maxWidth = 215
                    ) />

            <cfimage
                action="write"
                source="#_image#"
                overwrite="true"
                destination="#getXLargeThumbnailPath()#" />
        </cfif>

        <cfif   ARGUMENTS.overwriteExisting
            OR  NOT FileExists(getLargeThumbnailPath())>
            <cfset _image =
                REQUEST.UDFLib.Image.scale(
                    imagePath = ARGUMENTS.sourcePath,
                    maxHeight = 265,
                    maxWidth = 215
                    ) />

            <cfimage
                action="write"
                source="#_image#"
                overwrite="true"
                destination="#getLargeThumbnailPath()#" />
        </cfif>

        <cfif   ARGUMENTS.overwriteExisting
            OR  NOT FileExists(getMediumThumbnailPath())>
            <cfset _image =
                REQUEST.UDFLib.Image.scale(
                    imagePath = ARGUMENTS.sourcePath,
                    maxHeight = 100,
                    maxWidth = 100
                    ) />

            <cfimage
                action="write"
                source="#_image#"
                overwrite="true"
                destination="#getMediumThumbnailPath()#" />
        </cfif>

        <cfif   ARGUMENTS.overwriteExisting
            OR  NOT FileExists(getSmallThumbnailPath())>
            <cfset _image =
                REQUEST.UDFLib.Image.scale(
                    imagePath = ARGUMENTS.sourcePath,
                    maxHeight = 50,
                    maxWidth = 50
                    ) />

            <cfimage
                action="write"
                source="#_image#"
                overwrite="true"
                destination="#getSmallThumbnailPath()#" />
        </cfif>

        <cfscript>
            if  (ARGUMENTS.deleteSourceFile) {
                try {
                    FileDelete(ARGUMENTS.sourcePath);
                }
                catch (any e) {
                }
            }
        </cfscript>
    </cfif>
</cffunction>

REQUEST.UDFLib.PDF:

<cffunction
    name="pdfToImageFile"
    returntype="String"
    output="false"
    hint="Converts a phsyical PDF File to a physical Image file and returns the absolute path of the new Image file">
    <cfargument name="sourcePath" type="String" default="" />
    <cfargument name="destinationPath" type="String" default="" />
    <cfargument name="format" type="String" default="png" />

    <cfset var LOCAL = {} />

    <cfif NOT isValidPDF(Trim(ARGUMENTS.sourcePath))>
        <cfthrow
            message="Source file not specified or not a valid PDF file." />
    </cfif>

    <cfif NOT DirectoryExists(Trim(ARGUMENTS.destinationPath))>
        <cfthrow message="Inavlid Destination path." />
    </cfif>

    <cfif
        NOT ListFindNoCase(
                GetWriteableImageFormats(),
                Trim(ARGUMENTS.format)
                )>
        <cfthrow message="Inavlid Image format specified." />
    </cfif>

    <cfscript>
        LOCAL.DestinationFilePath =
                Trim(ARGUMENTS.destinationPath)
            &   "\"
            &   VARIABLES.Library.File.getFileNameWithoutExtension(
                    GetFileFromPath(ARGUMENTS.sourcePath)
                    )
            &   "."
            &   LCase(Trim(ARGUMENTS.format));

        LOCAL.RandomAccessFile =
            CreateObject("java", "java.io.RandomAccessFile")
                .init(
                    CreateObject("java","java.io.File")
                        .init(ARGUMENTS.sourcePath),
                    "r"
                    );

        LOCAL.FileChannel = LOCAL.RandomAccessFile.getChannel();
    </cfscript>

    <cftry>
        <cfset LOCAL.PDFFile =
            CreateObject("java", "com.sun.pdfview.PDFFile")
                .init(
                    LOCAL.FileChannel.map(
                        CreateObject("java", "java.nio.channels.FileChannel$MapMode")
                            .READ_ONLY,
                        0,
                        LOCAL.FileChannel.size()
                        )
                    ) />

        <cfset LOCAL.PDFPage = LOCAL.PDFFile.getPage(1) />

        <cfif NOT StructKeyExists(LOCAL, "PDFPage")>
            <cfthrow message="PDF cannot be converted - unknown error." />
        </cfif>

        <cfcatch type="Any">
            <cfscript>
                LOCAL.RandomAccessFile.close();
            </cfscript>

            <cfthrow message="PDF cannot be converted - unknown error." />
        </cfcatch>
    </cftry>

    <cfscript>
        //  Create new image
        LOCAL.Rectangle = LOCAL.PDFPage.getBBox();

        LOCAL.BufferedImage =
            CreateObject("java", "java.awt.image.BufferedImage")
                .init(
                    LOCAL.Rectangle.width,
                    LOCAL.Rectangle.height,
                    CreateObject("java", "java.awt.image.BufferedImage")
                        .TYPE_INT_RGB
                    );

        LOCAL.Graphics = LOCAL.BufferedImage.createGraphics();

        LOCAL.Graphics.drawImage(
            LOCAL.PDFPage.getImage(
                LOCAL.Rectangle.width,
                LOCAL.Rectangle.height,
                LOCAL.Rectangle,
                JavaCast("null", ""),
                true,
                true
                ),
            0,
            0,
            JavaCast("null", "")
            );

        LOCAL.Graphics.dispose();

        LOCAL.ImageFile =
            CreateObject("java", "java.io.File")
                .init(LOCAL.DestinationFilePath);

        //  Delete existing image file
        if  (LOCAL.ImageFile.exists())
            LOCAL.ImageFile.delete();

        //  Export the image to the specified format
        CreateObject("java", "javax.imageio.ImageIO")
            .write(
                LOCAL.BufferedImage,
                JavaCast("string", Trim(ARGUMENTS.format)),
                LOCAL.ImageFile
                );

        LOCAL.RandomAccessFile.close();

        return LOCAL.DestinationFilePath;
    </cfscript>
</cffunction>

REQUEST.UDFLib.Image:

<cffunction name="scale" returntype="Any" output="false">
    <cfargument name="imagePath" type="String" required="true" />
    <cfargument name="action" type="String" default="fit" hint="shrink, enlarge, or fit"/>
    <cfargument name="minWidth" type="Numeric" default="-1" />
    <cfargument name="minHeight" type="Numeric" default="-1" />
    <cfargument name="maxWidth" type="Numeric" default="-1" />
    <cfargument name="maxHeight" type="Numeric" default="-1" />

    <cfscript>
        var scaledDimensions = {
                width = -1,
                height = -1
            };
        var scaledImage = ImageNew();

        scaledImage = ImageNew(ARGUMENTS.imagePath);

        switch (ARGUMENTS.action) {
            case "shrink":
                scaledDimensions =
                    getDimensionsToShrink(
                        imageHeight = scaledImage.getHeight(),
                        imageWidth = scaledImage.getWidth(),
                        maxWidth = ARGUMENTS.maxWidth,
                        maxHeight = ARGUMENTS.maxHeight
                    );

                break;
            case "enlarge":
                scaledDimensions =
                    getDimensionsToEnlarge(
                        imageHeight = scaledImage.getHeight(),
                        imageWidth = scaledImage.getWidth(),
                        minWidth = ARGUMENTS.minWidth,
                        minHeight = ARGUMENTS.minHeight
                    );

                break;
            default:
                scaledDimensions =
                    getDimensionsToFit(
                        imageHeight = scaledImage.getHeight(),
                        imageWidth = scaledImage.getWidth(),
                        minWidth = ARGUMENTS.minWidth,
                        minHeight = ARGUMENTS.minHeight,
                        maxWidth = ARGUMENTS.maxWidth,
                        maxHeight = ARGUMENTS.maxHeight
                    );

                break;
        }

        if (scaledDimensions.width > 0 && scaledDimensions.height > 0) {
            // This helps the image quality
            ImageSetAntialiasing(scaledImage, "on");

            ImageScaleToFit(
                scaledImage,
                scaledDimensions.width,
                scaledDimensions.height
                );
        }

        return scaledImage;
    </cfscript>
</cffunction>

Thanks to @MarkAKruger for pointing me to CFROOT\runtime\bin\hs_err_pid*.log files. It looks like a memory issue when trying to convert the PDF to PNG....

Here is a link to the contents of the file from the last time I tried to run this template (to large to include here):

Error Dump File

I would still really appreciate any help figuring out how to fix.....

1
so start debugging: load the script up with debug output statements and figure out where it's crashing. - Marc B
What are you looking at that tells you ColdFusion is crashing and re-starting? - Dan Bracuk
If you remove all the PDFs added in the last 2 months since the errors started, any difference? How many files are we talking about? How big's the largest one? What's your code look like? - duncan
Have you even looked at the logs to check to see what they might be reporting is the problem? What actual troubleshooting have you actually done? - Adam Cameron
Eric, The error is clearly an out of memory error. As I said, CF tends to load images and resources associated with things like what you are trying to do in large heap objects - eventually killing the heap which is constrained by your Xms and Xmn variables (see your jvm.config file). Your options are to increase the heap size if possible (that's the easiest) or refactor your code to take the task in smaller bites over a longer period - as in a single request only handles 5 files. You just have to run it repeatedly... something like that. - Mark A Kruger

1 Answers

4
votes

Take a look in the /runtime/bin directory and see if you hav esome error files - something like hserrorxxxx.log (don't recall the format for java 1.4). This is a "hotspot" error - typically generated on a crash. Open one up and take a look. My guess is you are either running out of memory or there is an RGB image embedded in your PDF that is abending your server. You may be able to figure it out from the stack in the hs (hotspot) error file.