43#include "MagickCore/studio.h"
44#include "MagickCore/client.h"
45#include "MagickCore/exception.h"
46#include "MagickCore/exception-private.h"
47#include "MagickCore/linked-list.h"
48#include "MagickCore/locale_.h"
49#include "MagickCore/log.h"
50#include "MagickCore/magick.h"
51#include "MagickCore/memory_.h"
52#include "MagickCore/memory-private.h"
53#include "MagickCore/semaphore.h"
54#include "MagickCore/string_.h"
55#include "MagickCore/utility.h"
56#include "MagickCore/utility-private.h"
61#define MaxExceptionList 64
66#if defined(__cplusplus) || defined(c_plusplus)
71 DefaultErrorHandler(
const ExceptionType,
const char *,
const char *),
72 DefaultFatalErrorHandler(
const ExceptionType,
const char *,
const char *)
73 magick_attribute((__noreturn__)),
74 DefaultWarningHandler(
const ExceptionType,
const char *,
const char *);
76#if defined(__cplusplus) || defined(c_plusplus)
84 error_handler = DefaultErrorHandler;
86static FatalErrorHandler
87 fatal_error_handler = DefaultFatalErrorHandler;
90 warning_handler = DefaultWarningHandler;
121 exception=(
ExceptionInfo *) AcquireCriticalMemory(
sizeof(*exception));
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 >= WarningException) && (p->severity < ErrorException))
223 MagickWarning(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 >= FatalErrorException)
227 MagickFatalError(p->severity,p->reason,p->description);
228 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
230 UnlockSemaphoreInfo(exception->semaphore);
231 ClearMagickException(exception);
261 clone_exception=(
ExceptionInfo *) AcquireCriticalMemory(
sizeof(*exception));
262 InitializeExceptionInfo(clone_exception);
263 InheritException(clone_exception,exception);
264 clone_exception->relinquish=MagickTrue;
265 return(clone_exception);
296static void DefaultErrorHandler(
const ExceptionType magick_unused(severity),
297 const char *reason,
const char *description)
299 magick_unreferenced(severity);
301 if (reason == (
char *) NULL)
303 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
304 if (description != (
char *) NULL)
305 (void) FormatLocaleFile(stderr,
" (%s)",description);
306 (void) FormatLocaleFile(stderr,
".\n");
307 (void) fflush(stderr);
338static void DefaultFatalErrorHandler(
const ExceptionType severity,
339 const char *reason,
const char *description)
341 (void) FormatLocaleFile(stderr,
"%s:",GetClientName());
342 if (reason != (
char *) NULL)
343 (void) FormatLocaleFile(stderr,
" %s",reason);
344 if (description != (
char *) NULL)
345 (void) FormatLocaleFile(stderr,
" (%s)",description);
346 (void) FormatLocaleFile(stderr,
".\n");
347 (void) fflush(stderr);
348 MagickCoreTerminus();
349 exit((
int) (severity-FatalErrorException)+1);
380static void DefaultWarningHandler(
const ExceptionType magick_unused(severity),
381 const char *reason,
const char *description)
383 magick_unreferenced(severity);
385 if (reason == (
char *) NULL)
387 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
388 if (description != (
char *) NULL)
389 (void) FormatLocaleFile(stderr,
" (%s)",description);
390 (void) FormatLocaleFile(stderr,
".\n");
391 (void) fflush(stderr);
422 assert(exception->signature == MagickCoreSignature);
424 ActivateSemaphoreInfo(&exception->semaphore);
425 LockSemaphoreInfo(exception->semaphore);
426 exception->severity=UndefinedException;
427 if (exception->relinquish != MagickFalse)
429 exception->signature=(~MagickCoreSignature);
430 if (exception->exceptions != (
void *) NULL)
431 exception->exceptions=(
void *) DestroyLinkedList((
LinkedListInfo *)
432 exception->exceptions,DestroyExceptionElement);
435 if (exception->exceptions != (
void *) NULL)
437 DestroyExceptionElement);
438 relinquish=exception->relinquish;
439 UnlockSemaphoreInfo(exception->semaphore);
440 if (relinquish != MagickFalse)
442 RelinquishSemaphoreInfo(&exception->semaphore);
443 exception=(
ExceptionInfo *) RelinquishMagickMemory(exception);
466MagickPrivate MagickBooleanType ExceptionComponentGenesis(
void)
469 exception_semaphore=AcquireSemaphoreInfo();
491MagickPrivate
void ExceptionComponentTerminus(
void)
494 ActivateSemaphoreInfo(&exception_semaphore);
495 LockSemaphoreInfo(exception_semaphore);
496 UnlockSemaphoreInfo(exception_semaphore);
497 RelinquishSemaphoreInfo(&exception_semaphore);
523MagickExport
char *GetExceptionMessage(
const int error)
526 exception[MagickPathExtent];
529#if defined(MAGICKCORE_HAVE_STRERROR_R)
530#if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
531 (void) strerror_r(error,exception,
sizeof(exception));
533 (void) CopyMagickString(exception,strerror_r(error,exception,
534 sizeof(exception)),
sizeof(exception));
537 (void) CopyMagickString(exception,strerror(error),
sizeof(exception));
539 return(ConstantString(exception));
569static const char *ExceptionSeverityToTag(
const ExceptionType severity)
573 case ResourceLimitWarning:
return(
"Resource/Limit/Warning/");
574 case TypeWarning:
return(
"Type/Warning/");
575 case OptionWarning:
return(
"Option/Warning/");
576 case DelegateWarning:
return(
"Delegate/Warning/");
577 case MissingDelegateWarning:
return(
"Missing/Delegate/Warning/");
578 case CorruptImageWarning:
return(
"Corrupt/Image/Warning/");
579 case FileOpenWarning:
return(
"File/Open/Warning/");
580 case BlobWarning:
return(
"Blob/Warning/");
581 case StreamWarning:
return(
"Stream/Warning/");
582 case CacheWarning:
return(
"Cache/Warning/");
583 case CoderWarning:
return(
"Coder/Warning/");
584 case FilterWarning:
return(
"Filter/Warning/");
585 case ModuleWarning:
return(
"Module/Warning/");
586 case DrawWarning:
return(
"Draw/Warning/");
587 case ImageWarning:
return(
"Image/Warning/");
588 case WandWarning:
return(
"Wand/Warning/");
589 case XServerWarning:
return(
"XServer/Warning/");
590 case MonitorWarning:
return(
"Monitor/Warning/");
591 case RegistryWarning:
return(
"Registry/Warning/");
592 case ConfigureWarning:
return(
"Configure/Warning/");
593 case PolicyWarning:
return(
"Policy/Warning/");
594 case ResourceLimitError:
return(
"Resource/Limit/Error/");
595 case TypeError:
return(
"Type/Error/");
596 case OptionError:
return(
"Option/Error/");
597 case DelegateError:
return(
"Delegate/Error/");
598 case MissingDelegateError:
return(
"Missing/Delegate/Error/");
599 case CorruptImageError:
return(
"Corrupt/Image/Error/");
600 case FileOpenError:
return(
"File/Open/Error/");
601 case BlobError:
return(
"Blob/Error/");
602 case StreamError:
return(
"Stream/Error/");
603 case CacheError:
return(
"Cache/Error/");
604 case CoderError:
return(
"Coder/Error/");
605 case FilterError:
return(
"Filter/Error/");
606 case ModuleError:
return(
"Module/Error/");
607 case DrawError:
return(
"Draw/Error/");
608 case ImageError:
return(
"Image/Error/");
609 case WandError:
return(
"Wand/Error/");
610 case XServerError:
return(
"XServer/Error/");
611 case MonitorError:
return(
"Monitor/Error/");
612 case RegistryError:
return(
"Registry/Error/");
613 case ConfigureError:
return(
"Configure/Error/");
614 case PolicyError:
return(
"Policy/Error/");
615 case ResourceLimitFatalError:
return(
"Resource/Limit/FatalError/");
616 case TypeFatalError:
return(
"Type/FatalError/");
617 case OptionFatalError:
return(
"Option/FatalError/");
618 case DelegateFatalError:
return(
"Delegate/FatalError/");
619 case MissingDelegateFatalError:
return(
"Missing/Delegate/FatalError/");
620 case CorruptImageFatalError:
return(
"Corrupt/Image/FatalError/");
621 case FileOpenFatalError:
return(
"File/Open/FatalError/");
622 case BlobFatalError:
return(
"Blob/FatalError/");
623 case StreamFatalError:
return(
"Stream/FatalError/");
624 case CacheFatalError:
return(
"Cache/FatalError/");
625 case CoderFatalError:
return(
"Coder/FatalError/");
626 case FilterFatalError:
return(
"Filter/FatalError/");
627 case ModuleFatalError:
return(
"Module/FatalError/");
628 case DrawFatalError:
return(
"Draw/FatalError/");
629 case ImageFatalError:
return(
"Image/FatalError/");
630 case WandFatalError:
return(
"Wand/FatalError/");
631 case XServerFatalError:
return(
"XServer/FatalError/");
632 case MonitorFatalError:
return(
"Monitor/FatalError/");
633 case RegistryFatalError:
return(
"Registry/FatalError/");
634 case ConfigureFatalError:
return(
"Configure/FatalError/");
635 case PolicyFatalError:
return(
"Policy/FatalError/");
641MagickExport
const char *GetLocaleExceptionMessage(
const ExceptionType severity,
645 message[MagickPathExtent];
650 assert(tag != (
const char *) NULL);
651 (void) FormatLocaleString(message,MagickPathExtent,
"Exception/%s%s",
652 ExceptionSeverityToTag(severity),tag);
653 locale_message=GetLocaleMessage(message);
654 if (locale_message == (
const char *) NULL)
656 if (locale_message == message)
658 return(locale_message);
692 assert(exception->signature == MagickCoreSignature);
694 assert(relative->signature == MagickCoreSignature);
695 assert(exception != relative);
696 if (relative->exceptions == (
void *) NULL)
698 LockSemaphoreInfo(relative->semaphore);
701 relative->exceptions);
704 (void) ThrowException(exception,p->severity,p->reason,p->description);
706 relative->exceptions);
708 UnlockSemaphoreInfo(relative->semaphore);
733MagickPrivate
void InitializeExceptionInfo(
ExceptionInfo *exception)
736 (void) memset(exception,0,
sizeof(*exception));
737 exception->severity=UndefinedException;
738 exception->exceptions=(
void *) NewLinkedList(0);
739 exception->semaphore=AcquireSemaphoreInfo();
740 exception->signature=MagickCoreSignature;
771MagickExport
void MagickError(
const ExceptionType error,
const char *reason,
772 const char *description)
774 if (error_handler != (ErrorHandler) NULL)
775 (*error_handler)(error,reason,description);
807MagickExport
void MagickFatalError(
const ExceptionType error,
const char *reason,
808 const char *description)
810 if (fatal_error_handler != (FatalErrorHandler) NULL)
811 (*fatal_error_handler)(error,reason,description);
812 MagickCoreTerminus();
843MagickExport
void MagickWarning(
const ExceptionType warning,
const char *reason,
844 const char *description)
846 if (warning_handler != (WarningHandler) NULL)
847 (*warning_handler)(warning,reason,description);
873MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
879 ActivateSemaphoreInfo(&exception_semaphore);
880 LockSemaphoreInfo(exception_semaphore);
881 previous_handler=error_handler;
882 error_handler=handler;
883 UnlockSemaphoreInfo(exception_semaphore);
884 return(previous_handler);
910MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
916 ActivateSemaphoreInfo(&exception_semaphore);
917 LockSemaphoreInfo(exception_semaphore);
918 previous_handler=fatal_error_handler;
919 fatal_error_handler=handler;
920 UnlockSemaphoreInfo(exception_semaphore);
921 return(previous_handler);
947MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
953 ActivateSemaphoreInfo(&exception_semaphore);
954 LockSemaphoreInfo(exception_semaphore);
955 previous_handler=warning_handler;
956 warning_handler=handler;
957 UnlockSemaphoreInfo(exception_semaphore);
958 return(previous_handler);
992MagickExport MagickBooleanType ThrowException(
ExceptionInfo *exception,
993 const ExceptionType severity,
const char *reason,
const char *description)
1002 assert(exception->signature == MagickCoreSignature);
1003 LockSemaphoreInfo(exception->semaphore);
1005 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList)
1007 if (severity < ErrorException)
1009 UnlockSemaphoreInfo(exception->semaphore);
1013 if (p->severity >= ErrorException)
1015 UnlockSemaphoreInfo(exception->semaphore);
1020 if ((p != (
ExceptionInfo *) NULL) && (p->severity == severity) &&
1021 (LocaleCompare(exception->reason,reason) == 0) &&
1022 (LocaleCompare(exception->description,description) == 0))
1024 UnlockSemaphoreInfo(exception->semaphore);
1030 UnlockSemaphoreInfo(exception->semaphore);
1031 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1033 (void) memset(p,0,
sizeof(*p));
1034 p->severity=severity;
1035 if (reason != (
const char *) NULL)
1036 p->reason=ConstantString(reason);
1037 if (description != (
const char *) NULL)
1038 p->description=ConstantString(description);
1039 p->signature=MagickCoreSignature;
1040 (void) AppendValueToLinkedList(exceptions,p);
1041 if (p->severity > exception->severity)
1043 exception->severity=p->severity;
1044 exception->reason=p->reason;
1045 exception->description=p->description;
1047 UnlockSemaphoreInfo(exception->semaphore);
1048 if (GetNumberOfElementsInLinkedList(exceptions) == MaxExceptionList)
1049 (void) ThrowMagickException(exception,GetMagickModule(),
1050 ResourceLimitWarning,
"TooManyExceptions",
1051 "(exception processing is suspended)");
1094MagickExport MagickBooleanType ThrowMagickExceptionList(
1095 ExceptionInfo *exception,
const char *module,
const char *function,
1096 const size_t line,
const ExceptionType severity,
const char *tag,
1097 const char *format,va_list operands)
1100 message[MagickPathExtent],
1101 path[MagickPathExtent],
1102 reason[MagickPathExtent];
1118 assert(exception->signature == MagickCoreSignature);
1119 locale=GetLocaleExceptionMessage(severity,tag);
1120 (void) CopyMagickString(reason,locale,MagickPathExtent);
1121 (void) ConcatenateMagickString(reason,
" ",MagickPathExtent);
1122 length=strlen(reason);
1123#if defined(MAGICKCORE_HAVE_VSNPRINTF)
1124 n=vsnprintf(reason+length,MagickPathExtent-length,format,operands);
1126 n=vsprintf(reason+length,format,operands);
1129 reason[MagickPathExtent-1]=
'\0';
1130 status=LogMagickEvent(ExceptionEvent,module,function,line,
"%s",reason);
1131 GetPathComponent(module,TailPath,path);
1133 if ((severity >= WarningException) && (severity < ErrorException))
1135 if ((severity >= ErrorException) && (severity < FatalErrorException))
1137 if (severity >= FatalErrorException)
1139 (void) FormatLocaleString(message,MagickPathExtent,
"%s @ %s/%s/%s/%.20g",
1140 reason,type,path,function,(
double) line);
1141 (void) ThrowException(exception,severity,message,(
char *) NULL);
1145MagickExport MagickBooleanType ThrowMagickException(
ExceptionInfo *exception,
1146 const char *module,
const char *function,
const size_t line,
1147 const ExceptionType severity,
const char *tag,
const char *format,...)
1155 va_start(operands,format);
1156 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,