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 DefaultWarningHandler(
const ExceptionType,
const char *,
const char *);
73 #if defined(__cplusplus) || defined(c_plusplus)
81 error_handler = DefaultErrorHandler;
83 static FatalErrorHandler
84 fatal_error_handler = DefaultFatalErrorHandler;
87 warning_handler = DefaultWarningHandler;
118 exception=(
ExceptionInfo *) AcquireMagickMemory(
sizeof(*exception));
120 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
121 InitializeExceptionInfo(exception);
122 exception->relinquish=MagickTrue;
150 static void *DestroyExceptionElement(
void *exception)
156 if (p->reason != (
char *) NULL)
157 p->reason=DestroyString(p->reason);
158 if (p->description != (
char *) NULL)
159 p->description=DestroyString(p->description);
161 return((
void *) NULL);
164 MagickExport
void ClearMagickException(
ExceptionInfo *exception)
167 assert(exception->signature == MagickCoreSignature);
168 if (exception->exceptions == (
void *) NULL)
170 LockSemaphoreInfo(exception->semaphore);
172 DestroyExceptionElement);
173 exception->severity=UndefinedException;
174 exception->reason=(
char *) NULL;
175 exception->description=(
char *) NULL;
176 UnlockSemaphoreInfo(exception->semaphore);
215 assert(exception->signature == MagickCoreSignature);
216 if (exception->exceptions == (
void *) NULL)
218 LockSemaphoreInfo(exception->semaphore);
220 ResetLinkedListIterator(exceptions);
221 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
224 if (p->severity >= FatalErrorException)
225 MagickFatalError(p->severity,p->reason,p->description);
226 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
227 MagickError(p->severity,p->reason,p->description);
228 if ((p->severity >= WarningException) && (p->severity < ErrorException))
229 MagickWarning(p->severity,p->reason,p->description);
230 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
232 UnlockSemaphoreInfo(exception->semaphore);
233 ClearMagickException(exception);
263 clone_exception=(
ExceptionInfo *) AcquireMagickMemory(
sizeof(*exception));
265 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
266 InitializeExceptionInfo(clone_exception);
267 InheritException(clone_exception,exception);
268 clone_exception->relinquish=MagickTrue;
269 return(clone_exception);
300 static void DefaultErrorHandler(
const ExceptionType magick_unused(severity),
301 const char *reason,
const char *description)
303 magick_unreferenced(severity);
305 if (reason == (
char *) NULL)
307 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
308 if (description != (
char *) NULL)
309 (
void) FormatLocaleFile(stderr,
" (%s)",description);
310 (void) FormatLocaleFile(stderr,
".\n");
311 (void) fflush(stderr);
342 static void DefaultFatalErrorHandler(
const ExceptionType severity,
343 const char *reason,
const char *description)
345 if (reason == (
char *) NULL)
347 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
348 if (description != (
char *) NULL)
349 (
void) FormatLocaleFile(stderr,
" (%s)",description);
350 (void) FormatLocaleFile(stderr,
".\n");
351 (void) fflush(stderr);
352 MagickCoreTerminus();
353 exit((
int) (severity-FatalErrorException)+1);
384 static void DefaultWarningHandler(
const ExceptionType magick_unused(severity),
385 const char *reason,
const char *description)
387 magick_unreferenced(severity);
389 if (reason == (
char *) NULL)
391 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
392 if (description != (
char *) NULL)
393 (
void) FormatLocaleFile(stderr,
" (%s)",description);
394 (void) FormatLocaleFile(stderr,
".\n");
395 (void) fflush(stderr);
421 MagickPrivate MagickBooleanType ClearExceptionInfo(
ExceptionInfo *exception,
422 MagickBooleanType relinquish)
425 assert(exception->signature == MagickCoreSignature);
427 ActivateSemaphoreInfo(&exception->semaphore);
428 LockSemaphoreInfo(exception->semaphore);
429 if (relinquish == MagickFalse)
430 relinquish=exception->relinquish;
431 exception->severity=UndefinedException;
432 if (relinquish != MagickFalse)
434 exception->signature=(~MagickCoreSignature);
435 if (exception->exceptions != (
void *) NULL)
436 exception->exceptions=(
void *) DestroyLinkedList((
LinkedListInfo *)
437 exception->exceptions,DestroyExceptionElement);
439 else if (exception->exceptions != (
void *) NULL)
441 DestroyExceptionElement);
442 UnlockSemaphoreInfo(exception->semaphore);
443 if (relinquish != MagickFalse)
444 DestroySemaphoreInfo(&exception->semaphore);
450 if (ClearExceptionInfo(exception,MagickFalse) != MagickFalse)
451 exception=(
ExceptionInfo *) RelinquishMagickMemory(exception);
473 MagickPrivate MagickBooleanType ExceptionComponentGenesis(
void)
476 exception_semaphore=AllocateSemaphoreInfo();
498 MagickPrivate
void ExceptionComponentTerminus(
void)
501 ActivateSemaphoreInfo(&exception_semaphore);
502 LockSemaphoreInfo(exception_semaphore);
503 UnlockSemaphoreInfo(exception_semaphore);
504 DestroySemaphoreInfo(&exception_semaphore);
530 MagickExport
char *GetExceptionMessage(
const int error)
533 exception[MaxTextExtent];
536 #if defined(MAGICKCORE_HAVE_STRERROR_R)
537 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
538 (void) strerror_r(error,exception,
sizeof(exception));
540 (void) CopyMagickString(exception,strerror_r(error,exception,
541 sizeof(exception)),
sizeof(exception));
544 (void) CopyMagickString(exception,strerror(error),
sizeof(exception));
546 return(ConstantString(exception));
576 static const char *ExceptionSeverityToTag(
const ExceptionType severity)
580 case ResourceLimitWarning:
return(
"Resource/Limit/Warning/");
581 case TypeWarning:
return(
"Type/Warning/");
582 case OptionWarning:
return(
"Option/Warning/");
583 case DelegateWarning:
return(
"Delegate/Warning/");
584 case MissingDelegateWarning:
return(
"Missing/Delegate/Warning/");
585 case CorruptImageWarning:
return(
"Corrupt/Image/Warning/");
586 case FileOpenWarning:
return(
"File/Open/Warning/");
587 case BlobWarning:
return(
"Blob/Warning/");
588 case StreamWarning:
return(
"Stream/Warning/");
589 case CacheWarning:
return(
"Cache/Warning/");
590 case CoderWarning:
return(
"Coder/Warning/");
591 case FilterWarning:
return(
"Filter/Warning/");
592 case ModuleWarning:
return(
"Module/Warning/");
593 case DrawWarning:
return(
"Draw/Warning/");
594 case ImageWarning:
return(
"Image/Warning/");
595 case WandWarning:
return(
"Wand/Warning/");
596 case XServerWarning:
return(
"XServer/Warning/");
597 case MonitorWarning:
return(
"Monitor/Warning/");
598 case RegistryWarning:
return(
"Registry/Warning/");
599 case ConfigureWarning:
return(
"Configure/Warning/");
600 case PolicyWarning:
return(
"Policy/Warning/");
601 case ResourceLimitError:
return(
"Resource/Limit/Error/");
602 case TypeError:
return(
"Type/Error/");
603 case OptionError:
return(
"Option/Error/");
604 case DelegateError:
return(
"Delegate/Error/");
605 case MissingDelegateError:
return(
"Missing/Delegate/Error/");
606 case CorruptImageError:
return(
"Corrupt/Image/Error/");
607 case FileOpenError:
return(
"File/Open/Error/");
608 case BlobError:
return(
"Blob/Error/");
609 case StreamError:
return(
"Stream/Error/");
610 case CacheError:
return(
"Cache/Error/");
611 case CoderError:
return(
"Coder/Error/");
612 case FilterError:
return(
"Filter/Error/");
613 case ModuleError:
return(
"Module/Error/");
614 case DrawError:
return(
"Draw/Error/");
615 case ImageError:
return(
"Image/Error/");
616 case WandError:
return(
"Wand/Error/");
617 case XServerError:
return(
"XServer/Error/");
618 case MonitorError:
return(
"Monitor/Error/");
619 case RegistryError:
return(
"Registry/Error/");
620 case ConfigureError:
return(
"Configure/Error/");
621 case PolicyError:
return(
"Policy/Error/");
622 case ResourceLimitFatalError:
return(
"Resource/Limit/FatalError/");
623 case TypeFatalError:
return(
"Type/FatalError/");
624 case OptionFatalError:
return(
"Option/FatalError/");
625 case DelegateFatalError:
return(
"Delegate/FatalError/");
626 case MissingDelegateFatalError:
return(
"Missing/Delegate/FatalError/");
627 case CorruptImageFatalError:
return(
"Corrupt/Image/FatalError/");
628 case FileOpenFatalError:
return(
"File/Open/FatalError/");
629 case BlobFatalError:
return(
"Blob/FatalError/");
630 case StreamFatalError:
return(
"Stream/FatalError/");
631 case CacheFatalError:
return(
"Cache/FatalError/");
632 case CoderFatalError:
return(
"Coder/FatalError/");
633 case FilterFatalError:
return(
"Filter/FatalError/");
634 case ModuleFatalError:
return(
"Module/FatalError/");
635 case DrawFatalError:
return(
"Draw/FatalError/");
636 case ImageFatalError:
return(
"Image/FatalError/");
637 case WandFatalError:
return(
"Wand/FatalError/");
638 case XServerFatalError:
return(
"XServer/FatalError/");
639 case MonitorFatalError:
return(
"Monitor/FatalError/");
640 case RegistryFatalError:
return(
"Registry/FatalError/");
641 case ConfigureFatalError:
return(
"Configure/FatalError/");
642 case PolicyFatalError:
return(
"Policy/FatalError/");
648 MagickExport
const char *GetLocaleExceptionMessage(
const ExceptionType severity,
652 message[MaxTextExtent];
657 assert(tag != (
const char *) NULL);
658 (void) FormatLocaleString(message,MaxTextExtent,
"Exception/%s%s",
659 ExceptionSeverityToTag(severity),tag);
660 locale_message=GetLocaleMessage(message);
661 if (locale_message == (
const char *) NULL)
663 if (locale_message == message)
665 return(locale_message);
699 assert(exception->signature == MagickCoreSignature);
701 assert(relative->signature == MagickCoreSignature);
702 assert(exception != relative);
703 if (relative->exceptions == (
void *) NULL)
705 LockSemaphoreInfo(relative->semaphore);
708 relative->exceptions);
711 (void) ThrowException(exception,p->severity,p->reason,p->description);
713 relative->exceptions);
715 UnlockSemaphoreInfo(relative->semaphore);
740 MagickPrivate
void InitializeExceptionInfo(
ExceptionInfo *exception)
743 (void) memset(exception,0,
sizeof(*exception));
744 exception->severity=UndefinedException;
745 exception->exceptions=(
void *) NewLinkedList(0);
746 exception->semaphore=AllocateSemaphoreInfo();
747 exception->signature=MagickCoreSignature;
778 MagickExport
void MagickError(
const ExceptionType error,
const char *reason,
779 const char *description)
781 if (error_handler != (ErrorHandler) NULL)
782 (*error_handler)(error,reason,description);
814 MagickExport
void MagickFatalError(
const ExceptionType error,
const char *reason,
815 const char *description)
817 if (fatal_error_handler != (ErrorHandler) NULL)
818 (*fatal_error_handler)(error,reason,description);
848 MagickExport
void MagickWarning(
const ExceptionType warning,
const char *reason,
849 const char *description)
851 if (warning_handler != (WarningHandler) NULL)
852 (*warning_handler)(warning,reason,description);
878 MagickExport 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);
915 MagickExport 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);
952 MagickExport 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);
997 MagickExport 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)");
1098 MagickExport 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);
1149 MagickExport 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,