imagick
imagick copied to clipboard
ERROR_DELEGATE running ghostscript, only after a period of use
I have an HTTP server written in Go that uses this library to convert pages of PDF into images and save them on disk.
It works fine, but after a day or so of use the script begins consistently reporting an error. It may be a specific PDF file that initially triggers it, but I'm not sure yet.
This is the error that's thrown:
ERROR_DELEGATE: FailedToExecuteCommand `"gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r200x200" "-sOutputFile=/tmp/magick-24400PpSXLyVuSma4%d" "-f/tmp/magick-24400QWICA9Cnlcm4" "-f/tmp/magick-24400qFq7Wa4N4ay4"' (-1) @ error/delegate.c/ExternalDelegateCommand/461
Restarting the Go server consistently fixes the problem until it happens again. After the first time the error occurs, no further attempts are successful until the Go server is restarted.
This is the entire function for processing the PDF:
func processPDF(sourceFile string) ([]string, error) {
imagick.Initialize()
defer imagick.Terminate()
mw := imagick.NewMagickWand()
defer mw.Destroy()
var fileIdList []string
var data []byte
mw.SetResolution(200, 200)
err := mw.ReadImage(sourceFile)
if err != nil {
return nil, err
}
mw.SetIteratorIndex(0)
for {
mw.SetImageFormat("jpg")
data = mw.GetImageBlob()
addToDatabase(data)
fileIdList = append(fileIdList, fileHash)
lastInd := mw.GetIteratorIndex()
mw.SetIteratorIndex(int(lastInd) + 1)
if mw.GetIteratorIndex() == lastInd {
break
}
}
return fileIdList, nil
}
First, can you move the imagick.Initialize() and terminate out of your handler and into the main goroutine for your http server? It is a common mistake. You don't want to have your Web requests contending to start up and tear down ImageMagick every time.
I think I have seen this before when pdf are corrupt. Have you managed from your logs to isolate the pdf that breaks it and inspect that file? It's a shame to hear that the entire server stops working after this happens.
I had the there in hope that it would fix this error (given the nature of the problem I thought it might have some affect), but it didn't make any difference.
It seems to be under a sufficient load that this happens. That looked like a race condition to me, so for the sake of narrowing it down I threw a mutex lock around the whole function. Unfortunately it still happens :/
I should also clarify that I am using the legacy version of ImageMagick. I'm going to try upgrading to 6.9.9 tonight (right now the server is on 6.8.9), and see if that makes any difference. I feel like the way this issue persists indicates there's something terribly wrong with either ImageMagick itself or the MagicWand library. I mean, Ghostscript might fail once but it definitely doesn't keep doing it (under my assumption that imagemagick executes the program separately each time it needs to use it)
Its a good idea to focus on ImageMagick here, like you said. The only time I see delegate issues is with wrong library versions or ImageMagick bugs. Or running imagick in a alpine docker image with musl compiler
Could there be any issue with mw.GetLastError()
? Does creating a new instance of MagicWand guarantee that this error shouldn't persist?
I posted an issue on the ImageMagick GitHub as well: https://github.com/ImageMagick/ImageMagick6/issues/2
I haven't studied that part of the source, but I assumed it was a field on the wand that stores the error result of the last call using that wand.
Closing via the issue posted on the ImaegMagick issue tracker