BUG描述:
GraphicsMagick在处理多帧(multi-frames)图片(如GIF动画)时SyncBlob方法会修改后续帧的blob指针的指向:全部指向第一帧的blob!
如果后续处理过程中又调用到了SyncNextImageInList方法,继而SyncNextImageInList在调用ReferenceBlob的时候就会抛出下面的异常,从而导致进程退出:
server: ../GraphicsMagick-1.3.12/magick/semaphore.c:526: LockSemaphoreInfo: Assertion `semaphore_info->signature == 0xabacadabUL' failed.
注意:直接调用GraphicsMagick的gm命令处理处理多帧gif不会遇到上面的LockSemaphore异常;异常是发生在当你调用GraphicsMagick的API处理图片并试图获取图片的Blob数据的情况。
GraphicsMagick 1.3.12版本中的SyncBlob方法:
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
+ S y n c B l o b %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SyncBlob() flushes the datastream if it is a file or synchonizes the data
% attributes if it is an blob.
%
% The format of the SyncBlob method is:
%
% int SyncBlob(Image *image)
%
% A description of each parameter follows:
%
% o status: Method SyncBlob returns 0 on success; otherwise, it
% returns -1 and set errno to indicate the error.
%
% o image: The image.
%
%
*/
static int SyncBlob(Image *image)
{
int
status;
register Image
*p;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
assert(image->blob != (BlobInfo *) NULL);
assert(image->blob->type != UndefinedStream);
for (p=image; p->previous != (Image *) NULL; p=p->previous);
// 以下3行代码修改了后续帧的blob指针的指向:全部指向第一帧的blob
for ( ; p->next != (Image *) NULL; p=p->next)
if (p->blob != image->blob)
*p->blob=(*image->blob);
status=0;
switch (image->blob->type)
{
case UndefinedStream:
break;
case FileStream:
case StandardStream:
case PipeStream:
{
status=fflush(image->blob->file);
break;
}
case ZipStream:
{
#if defined(HasZLIB)
status=gzflush(image->blob->file,Z_SYNC_FLUSH);
#endif
break;
}
case BZipStream:
{
#if defined(HasBZLIB)
status=BZ2_bzflush(image->blob->file);
#endif
break;
}
case BlobStream:
break;
}
return(status);
}
修复方法:
1) 升级GraphicsMagick到更新的版本(2011-12-24 GraphicsMagick发布了1.3.13版本)
2) 手工剔除SyncBlob方法中的第4049~4052行(未经测试!)




最近评论