43#include "magick/studio.h"
44#include "magick/client.h"
45#include "magick/exception.h"
46#include "magick/exception-private.h"
47#include "magick/hashmap.h"
48#include "magick/locale_.h"
49#include "magick/log.h"
50#include "magick/magick.h"
51#include "magick/memory_.h"
52#include "magick/semaphore.h"
53#include "magick/string_.h"
54#include "magick/utility.h"
59#define MaxExceptionList 64
64#if defined(__cplusplus) || defined(c_plusplus)
69 DefaultErrorHandler(
const ExceptionType,
const char *,
const char *),
70 DefaultFatalErrorHandler(
const ExceptionType,
const char *,
const char *)
71 magick_attribute((__noreturn__)),
72 DefaultWarningHandler(
const ExceptionType,
const char *,
const char *);
74#if defined(__cplusplus) || defined(c_plusplus)
82 error_handler = DefaultErrorHandler;
84static FatalErrorHandler
85 fatal_error_handler = DefaultFatalErrorHandler;
88 warning_handler = DefaultWarningHandler;
119 exception=(
ExceptionInfo *) AcquireMagickMemory(
sizeof(*exception));
121 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
122 InitializeExceptionInfo(exception);
123 exception->relinquish=MagickTrue;
151static void *DestroyExceptionElement(
void *exception)
157 if (p->reason != (
char *) NULL)
158 p->reason=DestroyString(p->reason);
159 if (p->description != (
char *) NULL)
160 p->description=DestroyString(p->description);
162 return((
void *) NULL);
165MagickExport
void ClearMagickException(
ExceptionInfo *exception)
168 assert(exception->signature == MagickCoreSignature);
169 if (exception->exceptions == (
void *) NULL)
171 LockSemaphoreInfo(exception->semaphore);
173 DestroyExceptionElement);
174 exception->severity=UndefinedException;
175 exception->reason=(
char *) NULL;
176 exception->description=(
char *) NULL;
177 UnlockSemaphoreInfo(exception->semaphore);
213 assert(exception->signature == MagickCoreSignature);
214 if (exception->exceptions == (
void *) NULL)
216 LockSemaphoreInfo(exception->semaphore);
218 ResetLinkedListIterator(exceptions);
219 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
222 if (p->severity >= FatalErrorException)
223 MagickFatalError(p->severity,p->reason,p->description);
224 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
225 MagickError(p->severity,p->reason,p->description);
226 if ((p->severity >= WarningException) && (p->severity < ErrorException))
227 MagickWarning(p->severity,p->reason,p->description);
228 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
230 UnlockSemaphoreInfo(exception->semaphore);
231 ClearMagickException(exception);
261 clone_exception=(
ExceptionInfo *) AcquireMagickMemory(
sizeof(*exception));
263 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
264 InitializeExceptionInfo(clone_exception);
265 InheritException(clone_exception,exception);
266 clone_exception->relinquish=MagickTrue;
267 return(clone_exception);
298static void DefaultErrorHandler(
const ExceptionType magick_unused(severity),
299 const char *reason,
const char *description)
301 magick_unreferenced(severity);
303 if (reason == (
char *) NULL)
305 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
306 if (description != (
char *) NULL)
307 (void) FormatLocaleFile(stderr,
" (%s)",description);
308 (void) FormatLocaleFile(stderr,
".\n");
309 (void) fflush(stderr);
340static void DefaultFatalErrorHandler(
const ExceptionType severity,
341 const char *reason,
const char *description)
343 (void) FormatLocaleFile(stderr,
"%s:",GetClientName());
344 if (reason != (
char *) NULL)
345 (void) FormatLocaleFile(stderr,
" %s",reason);
346 if (description != (
char *) NULL)
347 (void) FormatLocaleFile(stderr,
" (%s)",description);
348 (void) FormatLocaleFile(stderr,
".\n");
349 (void) fflush(stderr);
350 MagickCoreTerminus();
351 exit((
int) (severity-FatalErrorException)+1);
382static void DefaultWarningHandler(
const ExceptionType magick_unused(severity),
383 const char *reason,
const char *description)
385 magick_unreferenced(severity);
387 if (reason == (
char *) NULL)
389 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
390 if (description != (
char *) NULL)
391 (void) FormatLocaleFile(stderr,
" (%s)",description);
392 (void) FormatLocaleFile(stderr,
".\n");
393 (void) fflush(stderr);
419MagickPrivate MagickBooleanType ClearExceptionInfo(
ExceptionInfo *exception,
420 MagickBooleanType relinquish)
423 assert(exception->signature == MagickCoreSignature);
425 ActivateSemaphoreInfo(&exception->semaphore);
426 LockSemaphoreInfo(exception->semaphore);
427 if (relinquish == MagickFalse)
428 relinquish=exception->relinquish;
429 exception->severity=UndefinedException;
430 if (relinquish != MagickFalse)
432 exception->signature=(~MagickCoreSignature);
433 if (exception->exceptions != (
void *) NULL)
434 exception->exceptions=(
void *) DestroyLinkedList((
LinkedListInfo *)
435 exception->exceptions,DestroyExceptionElement);
437 else if (exception->exceptions != (
void *) NULL)
439 DestroyExceptionElement);
440 UnlockSemaphoreInfo(exception->semaphore);
441 if (relinquish != MagickFalse)
442 DestroySemaphoreInfo(&exception->semaphore);
448 if (ClearExceptionInfo(exception,MagickFalse) != MagickFalse)
449 exception=(
ExceptionInfo *) RelinquishMagickMemory(exception);
471MagickPrivate MagickBooleanType ExceptionComponentGenesis(
void)
474 exception_semaphore=AllocateSemaphoreInfo();
496MagickPrivate
void ExceptionComponentTerminus(
void)
499 ActivateSemaphoreInfo(&exception_semaphore);
500 LockSemaphoreInfo(exception_semaphore);
501 UnlockSemaphoreInfo(exception_semaphore);
502 DestroySemaphoreInfo(&exception_semaphore);
528MagickExport
char *GetExceptionMessage(
const int error)
531 exception[MaxTextExtent];
534#if defined(MAGICKCORE_HAVE_STRERROR_R)
535#if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
536 (void) strerror_r(error,exception,
sizeof(exception));
538 (void) CopyMagickString(exception,strerror_r(error,exception,
539 sizeof(exception)),
sizeof(exception));
542 (void) CopyMagickString(exception,strerror(error),
sizeof(exception));
544 return(ConstantString(exception));
574static const char *ExceptionSeverityToTag(
const ExceptionType severity)
578 case ResourceLimitWarning:
return(
"Resource/Limit/Warning/");
579 case TypeWarning:
return(
"Type/Warning/");
580 case OptionWarning:
return(
"Option/Warning/");
581 case DelegateWarning:
return(
"Delegate/Warning/");
582 case MissingDelegateWarning:
return(
"Missing/Delegate/Warning/");
583 case CorruptImageWarning:
return(
"Corrupt/Image/Warning/");
584 case FileOpenWarning:
return(
"File/Open/Warning/");
585 case BlobWarning:
return(
"Blob/Warning/");
586 case StreamWarning:
return(
"Stream/Warning/");
587 case CacheWarning:
return(
"Cache/Warning/");
588 case CoderWarning:
return(
"Coder/Warning/");
589 case FilterWarning:
return(
"Filter/Warning/");
590 case ModuleWarning:
return(
"Module/Warning/");
591 case DrawWarning:
return(
"Draw/Warning/");
592 case ImageWarning:
return(
"Image/Warning/");
593 case WandWarning:
return(
"Wand/Warning/");
594 case XServerWarning:
return(
"XServer/Warning/");
595 case MonitorWarning:
return(
"Monitor/Warning/");
596 case RegistryWarning:
return(
"Registry/Warning/");
597 case ConfigureWarning:
return(
"Configure/Warning/");
598 case PolicyWarning:
return(
"Policy/Warning/");
599 case ResourceLimitError:
return(
"Resource/Limit/Error/");
600 case TypeError:
return(
"Type/Error/");
601 case OptionError:
return(
"Option/Error/");
602 case DelegateError:
return(
"Delegate/Error/");
603 case MissingDelegateError:
return(
"Missing/Delegate/Error/");
604 case CorruptImageError:
return(
"Corrupt/Image/Error/");
605 case FileOpenError:
return(
"File/Open/Error/");
606 case BlobError:
return(
"Blob/Error/");
607 case StreamError:
return(
"Stream/Error/");
608 case CacheError:
return(
"Cache/Error/");
609 case CoderError:
return(
"Coder/Error/");
610 case FilterError:
return(
"Filter/Error/");
611 case ModuleError:
return(
"Module/Error/");
612 case DrawError:
return(
"Draw/Error/");
613 case ImageError:
return(
"Image/Error/");
614 case WandError:
return(
"Wand/Error/");
615 case XServerError:
return(
"XServer/Error/");
616 case MonitorError:
return(
"Monitor/Error/");
617 case RegistryError:
return(
"Registry/Error/");
618 case ConfigureError:
return(
"Configure/Error/");
619 case PolicyError:
return(
"Policy/Error/");
620 case ResourceLimitFatalError:
return(
"Resource/Limit/FatalError/");
621 case TypeFatalError:
return(
"Type/FatalError/");
622 case OptionFatalError:
return(
"Option/FatalError/");
623 case DelegateFatalError:
return(
"Delegate/FatalError/");
624 case MissingDelegateFatalError:
return(
"Missing/Delegate/FatalError/");
625 case CorruptImageFatalError:
return(
"Corrupt/Image/FatalError/");
626 case FileOpenFatalError:
return(
"File/Open/FatalError/");
627 case BlobFatalError:
return(
"Blob/FatalError/");
628 case StreamFatalError:
return(
"Stream/FatalError/");
629 case CacheFatalError:
return(
"Cache/FatalError/");
630 case CoderFatalError:
return(
"Coder/FatalError/");
631 case FilterFatalError:
return(
"Filter/FatalError/");
632 case ModuleFatalError:
return(
"Module/FatalError/");
633 case DrawFatalError:
return(
"Draw/FatalError/");
634 case ImageFatalError:
return(
"Image/FatalError/");
635 case WandFatalError:
return(
"Wand/FatalError/");
636 case XServerFatalError:
return(
"XServer/FatalError/");
637 case MonitorFatalError:
return(
"Monitor/FatalError/");
638 case RegistryFatalError:
return(
"Registry/FatalError/");
639 case ConfigureFatalError:
return(
"Configure/FatalError/");
640 case PolicyFatalError:
return(
"Policy/FatalError/");
646MagickExport
const char *GetLocaleExceptionMessage(
const ExceptionType severity,
650 message[MaxTextExtent];
655 assert(tag != (
const char *) NULL);
656 (void) FormatLocaleString(message,MaxTextExtent,
"Exception/%s%s",
657 ExceptionSeverityToTag(severity),tag);
658 locale_message=GetLocaleMessage(message);
659 if (locale_message == (
const char *) NULL)
661 if (locale_message == message)
663 return(locale_message);
697 assert(exception->signature == MagickCoreSignature);
699 assert(relative->signature == MagickCoreSignature);
700 assert(exception != relative);
701 if (relative->exceptions == (
void *) NULL)
703 LockSemaphoreInfo(relative->semaphore);
706 relative->exceptions);
709 (void) ThrowException(exception,p->severity,p->reason,p->description);
711 relative->exceptions);
713 UnlockSemaphoreInfo(relative->semaphore);
738MagickPrivate
void InitializeExceptionInfo(
ExceptionInfo *exception)
741 (void) memset(exception,0,
sizeof(*exception));
742 exception->severity=UndefinedException;
743 exception->exceptions=(
void *) NewLinkedList(0);
744 exception->semaphore=AllocateSemaphoreInfo();
745 exception->signature=MagickCoreSignature;
776MagickExport
void MagickError(
const ExceptionType error,
const char *reason,
777 const char *description)
779 if (error_handler != (ErrorHandler) NULL)
780 (*error_handler)(error,reason,description);
812MagickExport
void MagickFatalError(
const ExceptionType error,
const char *reason,
813 const char *description)
815 if (fatal_error_handler != (FatalErrorHandler) NULL)
816 (*fatal_error_handler)(error,reason,description);
817 MagickCoreTerminus();
848MagickExport
void MagickWarning(
const ExceptionType warning,
const char *reason,
849 const char *description)
851 if (warning_handler != (WarningHandler) NULL)
852 (*warning_handler)(warning,reason,description);
878MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
884 ActivateSemaphoreInfo(&exception_semaphore);
885 LockSemaphoreInfo(exception_semaphore);
886 previous_handler=error_handler;
887 error_handler=handler;
888 UnlockSemaphoreInfo(exception_semaphore);
889 return(previous_handler);
915MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
921 ActivateSemaphoreInfo(&exception_semaphore);
922 LockSemaphoreInfo(exception_semaphore);
923 previous_handler=fatal_error_handler;
924 fatal_error_handler=handler;
925 UnlockSemaphoreInfo(exception_semaphore);
926 return(previous_handler);
952MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
958 ActivateSemaphoreInfo(&exception_semaphore);
959 LockSemaphoreInfo(exception_semaphore);
960 previous_handler=warning_handler;
961 warning_handler=handler;
962 UnlockSemaphoreInfo(exception_semaphore);
963 return(previous_handler);
997MagickExport MagickBooleanType ThrowException(
ExceptionInfo *exception,
998 const ExceptionType severity,
const char *reason,
const char *description)
1007 assert(exception->signature == MagickCoreSignature);
1008 LockSemaphoreInfo(exception->semaphore);
1010 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList)
1012 if (severity < ErrorException)
1014 UnlockSemaphoreInfo(exception->semaphore);
1018 if (p->severity >= ErrorException)
1020 UnlockSemaphoreInfo(exception->semaphore);
1025 if ((p != (
ExceptionInfo *) NULL) && (p->severity == severity) &&
1026 (LocaleCompare(exception->reason,reason) == 0) &&
1027 (LocaleCompare(exception->description,description) == 0))
1029 UnlockSemaphoreInfo(exception->semaphore);
1035 UnlockSemaphoreInfo(exception->semaphore);
1036 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1038 (void) memset(p,0,
sizeof(*p));
1039 p->severity=severity;
1040 if (reason != (
const char *) NULL)
1041 p->reason=ConstantString(reason);
1042 if (description != (
const char *) NULL)
1043 p->description=ConstantString(description);
1044 p->signature=MagickCoreSignature;
1045 (void) AppendValueToLinkedList(exceptions,p);
1046 if (p->severity > exception->severity)
1048 exception->severity=p->severity;
1049 exception->reason=p->reason;
1050 exception->description=p->description;
1052 UnlockSemaphoreInfo(exception->semaphore);
1053 if (GetNumberOfElementsInLinkedList(exceptions) == MaxExceptionList)
1054 (void) ThrowMagickException(exception,GetMagickModule(),
1055 ResourceLimitWarning,
"TooManyExceptions",
1056 "(exception processing is suspended)");
1098MagickExport MagickBooleanType ThrowMagickExceptionList(
1099 ExceptionInfo *exception,
const char *module,
const char *function,
1100 const size_t line,
const ExceptionType severity,
const char *tag,
1101 const char *format,va_list operands)
1104 message[MaxTextExtent],
1105 path[MaxTextExtent],
1106 reason[MaxTextExtent];
1122 assert(exception->signature == MagickCoreSignature);
1123 locale=GetLocaleExceptionMessage(severity,tag);
1124 (void) CopyMagickString(reason,locale,MaxTextExtent);
1125 (void) ConcatenateMagickString(reason,
" ",MaxTextExtent);
1126 length=strlen(reason);
1127#if defined(MAGICKCORE_HAVE_VSNPRINTF)
1128 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1130 n=vsprintf(reason+length,format,operands);
1133 reason[MaxTextExtent-1]=
'\0';
1134 status=LogMagickEvent(ExceptionEvent,module,function,line,
"%s",reason);
1135 GetPathComponent(module,TailPath,path);
1137 if ((severity >= WarningException) && (severity < ErrorException))
1139 if ((severity >= ErrorException) && (severity < FatalErrorException))
1141 if (severity >= FatalErrorException)
1143 (void) FormatLocaleString(message,MaxTextExtent,
"%s @ %s/%s/%s/%.20g",reason,
1144 type,path,function,(
double) line);
1145 (void) ThrowException(exception,severity,message,(
char *) NULL);
1149MagickExport MagickBooleanType ThrowMagickException(
ExceptionInfo *exception,
1150 const char *module,
const char *function,
const size_t line,
1151 const ExceptionType severity,
const char *tag,
const char *format,...)
1159 va_start(operands,format);
1160 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,