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);
212 assert(exception->signature == MagickCoreSignature);
213 if (exception->exceptions == (
void *) NULL)
215 LockSemaphoreInfo(exception->semaphore);
217 ResetLinkedListIterator(exceptions);
218 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
221 if (p->severity >= FatalErrorException)
222 MagickFatalError(p->severity,p->reason,p->description);
223 if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
224 MagickError(p->severity,p->reason,p->description);
225 if ((p->severity >= WarningException) && (p->severity < ErrorException))
226 MagickWarning(p->severity,p->reason,p->description);
227 p=(
const ExceptionInfo *) GetNextValueInLinkedList(exceptions);
229 UnlockSemaphoreInfo(exception->semaphore);
230 ClearMagickException(exception);
260 clone_exception=(
ExceptionInfo *) AcquireMagickMemory(
sizeof(*exception));
262 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
263 InitializeExceptionInfo(clone_exception);
264 InheritException(clone_exception,exception);
265 clone_exception->relinquish=MagickTrue;
266 return(clone_exception);
297 static void DefaultErrorHandler(
const ExceptionType magick_unused(severity),
298 const char *reason,
const char *description)
300 magick_unreferenced(severity);
302 if (reason == (
char *) NULL)
304 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
305 if (description != (
char *) NULL)
306 (
void) FormatLocaleFile(stderr,
" (%s)",description);
307 (void) FormatLocaleFile(stderr,
".\n");
308 (void) fflush(stderr);
339 static void DefaultFatalErrorHandler(
const ExceptionType severity,
340 const char *reason,
const char *description)
342 if (reason == (
char *) NULL)
344 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
345 if (description != (
char *) NULL)
346 (
void) FormatLocaleFile(stderr,
" (%s)",description);
347 (void) FormatLocaleFile(stderr,
".\n");
348 (void) fflush(stderr);
349 MagickCoreTerminus();
350 exit((
int) (severity-FatalErrorException)+1);
381 static void DefaultWarningHandler(
const ExceptionType magick_unused(severity),
382 const char *reason,
const char *description)
384 magick_unreferenced(severity);
386 if (reason == (
char *) NULL)
388 (void) FormatLocaleFile(stderr,
"%s: %s",GetClientName(),reason);
389 if (description != (
char *) NULL)
390 (
void) FormatLocaleFile(stderr,
" (%s)",description);
391 (void) FormatLocaleFile(stderr,
".\n");
392 (void) fflush(stderr);
418 MagickPrivate MagickBooleanType ClearExceptionInfo(
ExceptionInfo *exception,
419 MagickBooleanType relinquish)
422 assert(exception->signature == MagickCoreSignature);
424 ActivateSemaphoreInfo(&exception->semaphore);
425 LockSemaphoreInfo(exception->semaphore);
426 if (relinquish == MagickFalse)
427 relinquish=exception->relinquish;
428 exception->severity=UndefinedException;
429 if (relinquish != MagickFalse)
431 exception->signature=(~MagickCoreSignature);
432 if (exception->exceptions != (
void *) NULL)
433 exception->exceptions=(
void *) DestroyLinkedList((
LinkedListInfo *)
434 exception->exceptions,DestroyExceptionElement);
436 else if (exception->exceptions != (
void *) NULL)
438 DestroyExceptionElement);
439 UnlockSemaphoreInfo(exception->semaphore);
440 if (relinquish != MagickFalse)
441 DestroySemaphoreInfo(&exception->semaphore);
447 if (ClearExceptionInfo(exception,MagickFalse) != MagickFalse)
448 exception=(
ExceptionInfo *) RelinquishMagickMemory(exception);
470 MagickPrivate MagickBooleanType ExceptionComponentGenesis(
void)
473 exception_semaphore=AllocateSemaphoreInfo();
495 MagickPrivate
void ExceptionComponentTerminus(
void)
498 ActivateSemaphoreInfo(&exception_semaphore);
499 LockSemaphoreInfo(exception_semaphore);
500 UnlockSemaphoreInfo(exception_semaphore);
501 DestroySemaphoreInfo(&exception_semaphore);
527 MagickExport
char *GetExceptionMessage(
const int error)
530 exception[MaxTextExtent];
533 #if defined(MAGICKCORE_HAVE_STRERROR_R)
534 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P)
535 (void) strerror_r(error,exception,
sizeof(exception));
537 (void) CopyMagickString(exception,strerror_r(error,exception,
538 sizeof(exception)),
sizeof(exception));
541 (void) CopyMagickString(exception,strerror(error),
sizeof(exception));
543 return(ConstantString(exception));
573 static const char *ExceptionSeverityToTag(
const ExceptionType severity)
577 case ResourceLimitWarning:
return(
"Resource/Limit/Warning/");
578 case TypeWarning:
return(
"Type/Warning/");
579 case OptionWarning:
return(
"Option/Warning/");
580 case DelegateWarning:
return(
"Delegate/Warning/");
581 case MissingDelegateWarning:
return(
"Missing/Delegate/Warning/");
582 case CorruptImageWarning:
return(
"Corrupt/Image/Warning/");
583 case FileOpenWarning:
return(
"File/Open/Warning/");
584 case BlobWarning:
return(
"Blob/Warning/");
585 case StreamWarning:
return(
"Stream/Warning/");
586 case CacheWarning:
return(
"Cache/Warning/");
587 case CoderWarning:
return(
"Coder/Warning/");
588 case FilterWarning:
return(
"Filter/Warning/");
589 case ModuleWarning:
return(
"Module/Warning/");
590 case DrawWarning:
return(
"Draw/Warning/");
591 case ImageWarning:
return(
"Image/Warning/");
592 case WandWarning:
return(
"Wand/Warning/");
593 case XServerWarning:
return(
"XServer/Warning/");
594 case MonitorWarning:
return(
"Monitor/Warning/");
595 case RegistryWarning:
return(
"Registry/Warning/");
596 case ConfigureWarning:
return(
"Configure/Warning/");
597 case PolicyWarning:
return(
"Policy/Warning/");
598 case ResourceLimitError:
return(
"Resource/Limit/Error/");
599 case TypeError:
return(
"Type/Error/");
600 case OptionError:
return(
"Option/Error/");
601 case DelegateError:
return(
"Delegate/Error/");
602 case MissingDelegateError:
return(
"Missing/Delegate/Error/");
603 case CorruptImageError:
return(
"Corrupt/Image/Error/");
604 case FileOpenError:
return(
"File/Open/Error/");
605 case BlobError:
return(
"Blob/Error/");
606 case StreamError:
return(
"Stream/Error/");
607 case CacheError:
return(
"Cache/Error/");
608 case CoderError:
return(
"Coder/Error/");
609 case FilterError:
return(
"Filter/Error/");
610 case ModuleError:
return(
"Module/Error/");
611 case DrawError:
return(
"Draw/Error/");
612 case ImageError:
return(
"Image/Error/");
613 case WandError:
return(
"Wand/Error/");
614 case XServerError:
return(
"XServer/Error/");
615 case MonitorError:
return(
"Monitor/Error/");
616 case RegistryError:
return(
"Registry/Error/");
617 case ConfigureError:
return(
"Configure/Error/");
618 case PolicyError:
return(
"Policy/Error/");
619 case ResourceLimitFatalError:
return(
"Resource/Limit/FatalError/");
620 case TypeFatalError:
return(
"Type/FatalError/");
621 case OptionFatalError:
return(
"Option/FatalError/");
622 case DelegateFatalError:
return(
"Delegate/FatalError/");
623 case MissingDelegateFatalError:
return(
"Missing/Delegate/FatalError/");
624 case CorruptImageFatalError:
return(
"Corrupt/Image/FatalError/");
625 case FileOpenFatalError:
return(
"File/Open/FatalError/");
626 case BlobFatalError:
return(
"Blob/FatalError/");
627 case StreamFatalError:
return(
"Stream/FatalError/");
628 case CacheFatalError:
return(
"Cache/FatalError/");
629 case CoderFatalError:
return(
"Coder/FatalError/");
630 case FilterFatalError:
return(
"Filter/FatalError/");
631 case ModuleFatalError:
return(
"Module/FatalError/");
632 case DrawFatalError:
return(
"Draw/FatalError/");
633 case ImageFatalError:
return(
"Image/FatalError/");
634 case WandFatalError:
return(
"Wand/FatalError/");
635 case XServerFatalError:
return(
"XServer/FatalError/");
636 case MonitorFatalError:
return(
"Monitor/FatalError/");
637 case RegistryFatalError:
return(
"Registry/FatalError/");
638 case ConfigureFatalError:
return(
"Configure/FatalError/");
639 case PolicyFatalError:
return(
"Policy/FatalError/");
645 MagickExport
const char *GetLocaleExceptionMessage(
const ExceptionType severity,
649 message[MaxTextExtent];
654 assert(tag != (
const char *) NULL);
655 (void) FormatLocaleString(message,MaxTextExtent,
"Exception/%s%s",
656 ExceptionSeverityToTag(severity),tag);
657 locale_message=GetLocaleMessage(message);
658 if (locale_message == (
const char *) NULL)
660 if (locale_message == message)
662 return(locale_message);
696 assert(exception->signature == MagickCoreSignature);
698 assert(relative->signature == MagickCoreSignature);
699 assert(exception != relative);
700 if (relative->exceptions == (
void *) NULL)
702 LockSemaphoreInfo(relative->semaphore);
705 relative->exceptions);
708 (void) ThrowException(exception,p->severity,p->reason,p->description);
710 relative->exceptions);
712 UnlockSemaphoreInfo(relative->semaphore);
737 MagickPrivate
void InitializeExceptionInfo(
ExceptionInfo *exception)
740 (void) memset(exception,0,
sizeof(*exception));
741 exception->severity=UndefinedException;
742 exception->exceptions=(
void *) NewLinkedList(0);
743 exception->semaphore=AllocateSemaphoreInfo();
744 exception->signature=MagickCoreSignature;
775 MagickExport
void MagickError(
const ExceptionType error,
const char *reason,
776 const char *description)
778 if (error_handler != (ErrorHandler) NULL)
779 (*error_handler)(error,reason,description);
811 MagickExport
void MagickFatalError(
const ExceptionType error,
const char *reason,
812 const char *description)
814 if (fatal_error_handler != (ErrorHandler) NULL)
815 (*fatal_error_handler)(error,reason,description);
845 MagickExport
void MagickWarning(
const ExceptionType warning,
const char *reason,
846 const char *description)
848 if (warning_handler != (WarningHandler) NULL)
849 (*warning_handler)(warning,reason,description);
875 MagickExport 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);
912 MagickExport 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);
949 MagickExport 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);
994 MagickExport MagickBooleanType ThrowException(
ExceptionInfo *exception,
995 const ExceptionType severity,
const char *reason,
const char *description)
1004 assert(exception->signature == MagickCoreSignature);
1005 LockSemaphoreInfo(exception->semaphore);
1007 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList)
1009 if (severity < ErrorException)
1011 UnlockSemaphoreInfo(exception->semaphore);
1015 if (p->severity >= ErrorException)
1017 UnlockSemaphoreInfo(exception->semaphore);
1022 if ((p != (
ExceptionInfo *) NULL) && (p->severity == severity) &&
1023 (LocaleCompare(exception->reason,reason) == 0) &&
1024 (LocaleCompare(exception->description,description) == 0))
1026 UnlockSemaphoreInfo(exception->semaphore);
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)");
1095 MagickExport MagickBooleanType ThrowMagickExceptionList(
1096 ExceptionInfo *exception,
const char *module,
const char *
function,
1097 const size_t line,
const ExceptionType severity,
const char *tag,
1098 const char *format,va_list operands)
1101 message[MaxTextExtent],
1102 path[MaxTextExtent],
1103 reason[MaxTextExtent];
1119 assert(exception->signature == MagickCoreSignature);
1120 locale=GetLocaleExceptionMessage(severity,tag);
1121 (void) CopyMagickString(reason,locale,MaxTextExtent);
1122 (void) ConcatenateMagickString(reason,
" ",MaxTextExtent);
1123 length=strlen(reason);
1124 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
1125 n=vsnprintf(reason+length,MaxTextExtent-length,format,operands);
1127 n=vsprintf(reason+length,format,operands);
1130 reason[MaxTextExtent-1]=
'\0';
1131 status=LogMagickEvent(ExceptionEvent,module,
function,line,
"%s",reason);
1132 GetPathComponent(module,TailPath,path);
1134 if ((severity >= WarningException) && (severity < ErrorException))
1136 if ((severity >= ErrorException) && (severity < FatalErrorException))
1138 if (severity >= FatalErrorException)
1140 (void) FormatLocaleString(message,MaxTextExtent,
"%s @ %s/%s/%s/%.20g",reason,
1141 type,path,
function,(
double) line);
1142 (void) ThrowException(exception,severity,message,(
char *) NULL);
1146 MagickExport MagickBooleanType ThrowMagickException(
ExceptionInfo *exception,
1147 const char *module,
const char *
function,
const size_t line,
1148 const ExceptionType severity,
const char *tag,
const char *format,...)
1156 va_start(operands,format);
1157 status=ThrowMagickExceptionList(exception,module,
function,line,severity,tag,