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;
116MagickExport ExceptionInfo *AcquireExceptionInfo(
void)
121 exception=(ExceptionInfo *) AcquireCriticalMemory(
sizeof(*exception));
122 InitializeExceptionInfo(exception);
123 exception->relinquish=MagickTrue;
151static void *DestroyExceptionElement(
void *exception)
156 p=(ExceptionInfo *) 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);
161 p=(ExceptionInfo *) RelinquishMagickMemory(p);
162 return((
void *) NULL);
165MagickExport
void ClearMagickException(ExceptionInfo *exception)
167 assert(exception != (ExceptionInfo *) NULL);
168 assert(exception->signature == MagickCoreSignature);
169 if (exception->exceptions == (
void *) NULL)
171 LockSemaphoreInfo(exception->semaphore);
172 ClearLinkedList((LinkedListInfo *) exception->exceptions,
173 DestroyExceptionElement);
174 exception->severity=UndefinedException;
175 exception->reason=(
char *) NULL;
176 exception->description=(
char *) NULL;
177 UnlockSemaphoreInfo(exception->semaphore);
204MagickExport
void CatchException(ExceptionInfo *exception)
212 assert(exception != (ExceptionInfo *) NULL);
213 assert(exception->signature == MagickCoreSignature);
214 if (exception->exceptions == (
void *) NULL)
216 LockSemaphoreInfo(exception->semaphore);
217 exceptions=(LinkedListInfo *) exception->exceptions;
218 ResetLinkedListIterator(exceptions);
219 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
220 while (p != (
const ExceptionInfo *) NULL)
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);
256MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *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);
416MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception)
421 assert(exception != (ExceptionInfo *) NULL);
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)
436 ClearLinkedList((LinkedListInfo *) exception->exceptions,
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));
536#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
537 strerror_s(exception,
sizeof(exception),error);
539 (void) CopyMagickString(exception,strerror(error),
sizeof(exception));
541 return(ConstantString(exception));
571static const char *ExceptionSeverityToTag(
const ExceptionType severity)
575 case ResourceLimitWarning:
return(
"Resource/Limit/Warning/");
576 case TypeWarning:
return(
"Type/Warning/");
577 case OptionWarning:
return(
"Option/Warning/");
578 case DelegateWarning:
return(
"Delegate/Warning/");
579 case MissingDelegateWarning:
return(
"Missing/Delegate/Warning/");
580 case CorruptImageWarning:
return(
"Corrupt/Image/Warning/");
581 case FileOpenWarning:
return(
"File/Open/Warning/");
582 case BlobWarning:
return(
"Blob/Warning/");
583 case StreamWarning:
return(
"Stream/Warning/");
584 case CacheWarning:
return(
"Cache/Warning/");
585 case CoderWarning:
return(
"Coder/Warning/");
586 case FilterWarning:
return(
"Filter/Warning/");
587 case ModuleWarning:
return(
"Module/Warning/");
588 case DrawWarning:
return(
"Draw/Warning/");
589 case ImageWarning:
return(
"Image/Warning/");
590 case WandWarning:
return(
"Wand/Warning/");
591 case XServerWarning:
return(
"XServer/Warning/");
592 case MonitorWarning:
return(
"Monitor/Warning/");
593 case RegistryWarning:
return(
"Registry/Warning/");
594 case ConfigureWarning:
return(
"Configure/Warning/");
595 case PolicyWarning:
return(
"Policy/Warning/");
596 case ResourceLimitError:
return(
"Resource/Limit/Error/");
597 case TypeError:
return(
"Type/Error/");
598 case OptionError:
return(
"Option/Error/");
599 case DelegateError:
return(
"Delegate/Error/");
600 case MissingDelegateError:
return(
"Missing/Delegate/Error/");
601 case CorruptImageError:
return(
"Corrupt/Image/Error/");
602 case FileOpenError:
return(
"File/Open/Error/");
603 case BlobError:
return(
"Blob/Error/");
604 case StreamError:
return(
"Stream/Error/");
605 case CacheError:
return(
"Cache/Error/");
606 case CoderError:
return(
"Coder/Error/");
607 case FilterError:
return(
"Filter/Error/");
608 case ModuleError:
return(
"Module/Error/");
609 case DrawError:
return(
"Draw/Error/");
610 case ImageError:
return(
"Image/Error/");
611 case WandError:
return(
"Wand/Error/");
612 case XServerError:
return(
"XServer/Error/");
613 case MonitorError:
return(
"Monitor/Error/");
614 case RegistryError:
return(
"Registry/Error/");
615 case ConfigureError:
return(
"Configure/Error/");
616 case PolicyError:
return(
"Policy/Error/");
617 case ResourceLimitFatalError:
return(
"Resource/Limit/FatalError/");
618 case TypeFatalError:
return(
"Type/FatalError/");
619 case OptionFatalError:
return(
"Option/FatalError/");
620 case DelegateFatalError:
return(
"Delegate/FatalError/");
621 case MissingDelegateFatalError:
return(
"Missing/Delegate/FatalError/");
622 case CorruptImageFatalError:
return(
"Corrupt/Image/FatalError/");
623 case FileOpenFatalError:
return(
"File/Open/FatalError/");
624 case BlobFatalError:
return(
"Blob/FatalError/");
625 case StreamFatalError:
return(
"Stream/FatalError/");
626 case CacheFatalError:
return(
"Cache/FatalError/");
627 case CoderFatalError:
return(
"Coder/FatalError/");
628 case FilterFatalError:
return(
"Filter/FatalError/");
629 case ModuleFatalError:
return(
"Module/FatalError/");
630 case DrawFatalError:
return(
"Draw/FatalError/");
631 case ImageFatalError:
return(
"Image/FatalError/");
632 case WandFatalError:
return(
"Wand/FatalError/");
633 case XServerFatalError:
return(
"XServer/FatalError/");
634 case MonitorFatalError:
return(
"Monitor/FatalError/");
635 case RegistryFatalError:
return(
"Registry/FatalError/");
636 case ConfigureFatalError:
return(
"Configure/FatalError/");
637 case PolicyFatalError:
return(
"Policy/FatalError/");
643MagickExport
const char *GetLocaleExceptionMessage(
const ExceptionType severity,
647 message[MagickPathExtent];
652 assert(tag != (
const char *) NULL);
653 (void) FormatLocaleString(message,MagickPathExtent,
"Exception/%s%s",
654 ExceptionSeverityToTag(severity),tag);
655 locale_message=GetLocaleMessage(message);
656 if (locale_message == (
const char *) NULL)
658 if (locale_message == message)
660 return(locale_message);
687MagickExport
void InheritException(ExceptionInfo *exception,
688 const ExceptionInfo *relative)
693 assert(exception != (ExceptionInfo *) NULL);
694 assert(exception->signature == MagickCoreSignature);
695 assert(relative != (ExceptionInfo *) NULL);
696 assert(relative->signature == MagickCoreSignature);
697 assert(exception != relative);
698 if (relative->exceptions == (
void *) NULL)
700 LockSemaphoreInfo(relative->semaphore);
701 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions);
702 p=(
const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
703 relative->exceptions);
704 while (p != (
const ExceptionInfo *) NULL)
706 (void) ThrowException(exception,p->severity,p->reason,p->description);
707 p=(
const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
708 relative->exceptions);
710 UnlockSemaphoreInfo(relative->semaphore);
735MagickPrivate
void InitializeExceptionInfo(ExceptionInfo *exception)
737 assert(exception != (ExceptionInfo *) NULL);
738 (void) memset(exception,0,
sizeof(*exception));
739 exception->severity=UndefinedException;
740 exception->exceptions=(
void *) NewLinkedList(0);
741 exception->semaphore=AcquireSemaphoreInfo();
742 exception->signature=MagickCoreSignature;
773MagickExport
void MagickError(
const ExceptionType error,
const char *reason,
774 const char *description)
776 if (error_handler != (ErrorHandler) NULL)
777 (*error_handler)(error,reason,description);
809MagickExport
void MagickFatalError(
const ExceptionType error,
const char *reason,
810 const char *description)
812 if (fatal_error_handler != (FatalErrorHandler) NULL)
813 (*fatal_error_handler)(error,reason,description);
814 MagickCoreTerminus();
845MagickExport
void MagickWarning(
const ExceptionType warning,
const char *reason,
846 const char *description)
848 if (warning_handler != (WarningHandler) NULL)
849 (*warning_handler)(warning,reason,description);
875MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
881 ActivateSemaphoreInfo(&exception_semaphore);
882 LockSemaphoreInfo(exception_semaphore);
883 previous_handler=error_handler;
884 error_handler=handler;
885 UnlockSemaphoreInfo(exception_semaphore);
886 return(previous_handler);
912MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
918 ActivateSemaphoreInfo(&exception_semaphore);
919 LockSemaphoreInfo(exception_semaphore);
920 previous_handler=fatal_error_handler;
921 fatal_error_handler=handler;
922 UnlockSemaphoreInfo(exception_semaphore);
923 return(previous_handler);
949MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
955 ActivateSemaphoreInfo(&exception_semaphore);
956 LockSemaphoreInfo(exception_semaphore);
957 previous_handler=warning_handler;
958 warning_handler=handler;
959 UnlockSemaphoreInfo(exception_semaphore);
960 return(previous_handler);
994MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception,
995 const ExceptionType severity,
const char *reason,
const char *description)
1003 assert(exception != (ExceptionInfo *) NULL);
1004 assert(exception->signature == MagickCoreSignature);
1005 LockSemaphoreInfo(exception->semaphore);
1006 exceptions=(LinkedListInfo *) exception->exceptions;
1007 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList)
1009 if (severity < ErrorException)
1011 UnlockSemaphoreInfo(exception->semaphore);
1014 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions);
1015 if (p->severity >= ErrorException)
1017 UnlockSemaphoreInfo(exception->semaphore);
1021 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions);
1022 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) &&
1023 (LocaleCompare(exception->reason,reason) == 0) &&
1024 (LocaleCompare(exception->description,description) == 0))
1026 UnlockSemaphoreInfo(exception->semaphore);
1029 p=(ExceptionInfo *) AcquireMagickMemory(
sizeof(*p));
1030 if (p == (ExceptionInfo *) NULL)
1032 UnlockSemaphoreInfo(exception->semaphore);
1033 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1035 (void) memset(p,0,
sizeof(*p));
1036 p->severity=severity;
1037 if (reason != (
const char *) NULL)
1038 p->reason=ConstantString(reason);
1039 if (description != (
const char *) NULL)
1040 p->description=ConstantString(description);
1041 p->signature=MagickCoreSignature;
1042 (void) AppendValueToLinkedList(exceptions,p);
1043 if (p->severity > exception->severity)
1045 exception->severity=p->severity;
1046 exception->reason=p->reason;
1047 exception->description=p->description;
1049 UnlockSemaphoreInfo(exception->semaphore);
1050 if (GetNumberOfElementsInLinkedList(exceptions) == MaxExceptionList)
1051 (void) ThrowMagickException(exception,GetMagickModule(),
1052 ResourceLimitWarning,
"TooManyExceptions",
1053 "(exception processing is suspended)");
1096MagickExport MagickBooleanType ThrowMagickExceptionList(
1097 ExceptionInfo *exception,
const char *module,
const char *function,
1098 const size_t line,
const ExceptionType severity,
const char *tag,
1099 const char *format,va_list operands)
1102 message[MagickPathExtent],
1103 path[MagickPathExtent],
1104 reason[MagickPathExtent];
1119 assert(exception != (ExceptionInfo *) NULL);
1120 assert(exception->signature == MagickCoreSignature);
1121 locale=GetLocaleExceptionMessage(severity,tag);
1122 (void) CopyMagickString(reason,locale,MagickPathExtent);
1123 (void) ConcatenateMagickString(reason,
" ",MagickPathExtent);
1124 length=strlen(reason);
1125#if defined(MAGICKCORE_HAVE_VSNPRINTF)
1126 n=vsnprintf(reason+length,MagickPathExtent-length,format,operands);
1128 n=vsprintf(reason+length,format,operands);
1131 reason[MagickPathExtent-1]=
'\0';
1132 status=LogMagickEvent(ExceptionEvent,module,function,line,
"%s",reason);
1133 GetPathComponent(module,TailPath,path);
1135 if ((severity >= WarningException) && (severity < ErrorException))
1137 if ((severity >= ErrorException) && (severity < FatalErrorException))
1139 if (severity >= FatalErrorException)
1141 (void) FormatLocaleString(message,MagickPathExtent,
"%s @ %s/%s/%s/%.20g",
1142 reason,type,path,function,(
double) line);
1143 (void) ThrowException(exception,severity,message,(
char *) NULL);
1147MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception,
1148 const char *module,
const char *function,
const size_t line,
1149 const ExceptionType severity,
const char *tag,
const char *format,...)
1157 va_start(operands,format);
1158 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag,