Search code examples
coldfusioncoldfusion-8

Why is ColdFusion crashing/restarting every time a certain template is called?


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.....


Solution

  • 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.