I've written a little PHP class that basically calls gm convert
from GraphicksMagick 1.3.12 via exec() to resize a picture. Users from the live site are reporting issues and I've been able to reproduce some problems in my development box as well.
The relevant code looks like this:
<?php
define('GM_PATH', 'C:\\Archivos de programa\\GraphicsMagick-1.3.12-Q16\\gm.exe');
[...]
private function resize($width, $height, $do_not_upscale=TRUE){
$source = escapeshellarg($this->source_file);
$target = escapeshellarg($this->target_file);
$command = escapeshellarg(GM_PATH) . ' convert ';
$parameters = array();
$parameters[] = $source;
$parameters[] = sprintf('-resize "%dx%d%s"', round($width), round($height), $do_not_upscale ? '>' : '');
$parameters[] = '+profile "*"';
$parameters[] = $target;
$execute = $command . ' ' . implode(' ', $parameters) . ' 2>&1';
exec($execute, $output, $return);
if( $return==0 ){
return $this->target_file;
}else{
throw new Exception('Image resizing failed: return code ' . $return . ': ' . implode(PHP_EOL, $output));
}
}
Live site runs under PHP/5.2.9-2 and dev site runs PHP/5.3.0. Both boxes run Windows Server 2003, Apache/2.2 and GraphicsMagick 1.3.112 Q16.
In live site I'm getting an exception with return code 1
. In dev site I can randomly see how a cmd.exe
process stays idle forever, using 0% CPU until I kill the task.
Given it's an external tool, I've run out of ideas about what to do next. How can I troubleshoot this issue?
Update #1
I fixed a little bug in an unrelated piece of code and I'm logging into a file every individual step I could think of (including gm.exe
's activity with -debug All
) but I'm going nowhere. PHP reaches the exec() call and gm.exe
remains running forever doing nothing.
Update #2
I've got the exact command being executed by two means. An echo into a log file shows this:
"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" convert -debug All "\\SHARE\Project\tmp\mini_4d13465d4bc4b.jpg" -resize "1024x1024>" +profile "*" "\\SHARE\Project\tmp\mini_4d13465dafddd.jpg" 2>>"//SHARE/Project/Miniatura-01.log"
In the process properties as shown by Process Explorer the command line looks like this:
cmd.exe /c ""C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" convert -debug All "\\SHARE\Project\tmp\mini_4d13465d4bc4b.jpg" -resize "1024x1024>" +profile "*" "\\SHARE\Project\tmp\mini_4d13465dafddd.jpg" 2>>"//SHARE/Project/Miniatura-01.log""
I'm able to run both commands manually although the second one only runs from Start->Run (not from a command prompt) unless I double quote the whole expression.
In any case, I'm reasonably sure that the command gets executed as expected because I do get the resized image all the times and the debug log generated by gm looks normal. The the last line always looks like this, when it stalls and when it doesn't:
13:53:52 0:03 3.016u 2344 module.c/UnloadModule/2180/Configure: Unloading "JPEG" module ...
I suspect there's something that prevents the process from exiting when done: a virus scanner, a shell extension or something...
The whole thing is starting to not be worth the effort of being fixed. I'll consider switching to ImageMagick or plain PHP function images.
Update #3
Funny... I've switched to ImageMagick and I'm getting the same exact issue! And I can reproduce it always: I just need to open two browser tabs.
It's obvious that I've forgotten how to run commands from PHP. I think I'll try to resize the picture with pure PHP code.
I found the solution thanks to a co-worker:
http://es2.php.net/manual/en/function.exec.php#99781
On Windows-Apache-PHP servers there is a problem with using the exec command more than once at the same time. If a script (with the exec command) is loaded more than once by the same user at the same time the server will freeze. In my case the PHP script using the exec command was used as the source of an image tag. More than one image in one HTML made the server stop. The problem is described here (http://bugs.php.net/bug.php?id=44942) toghether with a solution - stop the session before the exec command and start it again after it.
<?php
session_write_close();
exec($cmd);
session_start();
?>