1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % EEEEE X X CCCC EEEEE PPPP TTTTT IIIII OOO N N % 7 % E X X C E P P T I O O NN N % 8 % EEE X C EEE PPPP T I O O N N N % 9 % E X X C E P T I O O N NN % 10 % EEEEE X X CCCC EEEEE P T IIIII OOO N N % 11 % % 12 % % 13 % MagickCore Exception Methods % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1993 % 18 % % 19 % % 20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % https://imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 % 38 */ 39 40 /* 42 Include declarations. 43 */ 44 #include "MagickCore/studio.h" 45 #include "MagickCore/client.h" 46 #include "MagickCore/exception.h" 47 #include "MagickCore/exception-private.h" 48 #include "MagickCore/linked-list.h" 49 #include "MagickCore/locale_.h" 50 #include "MagickCore/log.h" 51 #include "MagickCore/magick.h" 52 #include "MagickCore/memory_.h" 53 #include "MagickCore/memory-private.h" 54 #include "MagickCore/string_.h" 55 #include "MagickCore/utility.h" 56 #include "MagickCore/utility-private.h" 57 58 /* 60 Define declarations. 61 */ 62 #define MaxExceptionList 64 63 64 /* 66 Forward declarations. 67 */ 68 #if defined(__cplusplus) || defined(c_plusplus) 69 extern "C" { 70 #endif 71 72 static void 73 DefaultErrorHandler(const ExceptionType,const char *,const char *), 74 DefaultFatalErrorHandler(const ExceptionType,const char *,const char *), 75 DefaultWarningHandler(const ExceptionType,const char *,const char *); 76 77 #if defined(__cplusplus) || defined(c_plusplus) 78 } 79 #endif 80 81 /* 83 Global declarations. 84 */ 85 static ErrorHandler 86 error_handler = DefaultErrorHandler; 87 88 static FatalErrorHandler 89 fatal_error_handler = DefaultFatalErrorHandler; 90 91 static WarningHandler 92 warning_handler = DefaultWarningHandler; 93 94 /* 96 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 97 % % 98 % % 99 % % 100 % A c q u i r e E x c e p t i o n I n f o % 101 % % 102 % % 103 % % 104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 105 % 106 % AcquireExceptionInfo() allocates the ExceptionInfo structure. 107 % 108 % The format of the AcquireExceptionInfo method is: 109 % 110 % ExceptionInfo *AcquireExceptionInfo(void) 111 % 112 */ 113 MagickExport ExceptionInfo *AcquireExceptionInfo(void) 114 { 115 ExceptionInfo 116 *exception; 117 118 exception=(ExceptionInfo *) AcquireCriticalMemory(sizeof(*exception)); 119 InitializeExceptionInfo(exception); 120 exception->relinquish=MagickTrue; 121 return(exception); 122 } 123 124 /*l 126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 127 % % 128 % % 129 % % 130 % C l e a r M a g i c k E x c e p t i o n % 131 % % 132 % % 133 % % 134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 135 % 136 % ClearMagickException() clears any exception that may not have been caught 137 % yet. 138 % 139 % The format of the ClearMagickException method is: 140 % 141 % ClearMagickException(ExceptionInfo *exception) 142 % 143 % A description of each parameter follows: 144 % 145 % o exception: the exception info. 146 % 147 */ 148 149 static void *DestroyExceptionElement(void *exception) 150 { 151 register ExceptionInfo 152 *p; 153 154 p=(ExceptionInfo *) exception; 155 if (p->reason != (char *) NULL) 156 p->reason=DestroyString(p->reason); 157 if (p->description != (char *) NULL) 158 p->description=DestroyString(p->description); 159 p=(ExceptionInfo *) RelinquishMagickMemory(p); 160 return((void *) NULL); 161 } 162 163 MagickExport void ClearMagickException(ExceptionInfo *exception) 164 { 165 assert(exception != (ExceptionInfo *) NULL); 166 assert(exception->signature == MagickCoreSignature); 167 if (exception->exceptions == (void *) NULL) 168 return; 169 LockSemaphoreInfo(exception->semaphore); 170 ClearLinkedList((LinkedListInfo *) exception->exceptions, 171 DestroyExceptionElement); 172 exception->severity=UndefinedException; 173 exception->reason=(char *) NULL; 174 exception->description=(char *) NULL; 175 UnlockSemaphoreInfo(exception->semaphore); 176 errno=0; 177 } 178 179 /* 181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 182 % % 183 % % 184 % % 185 % C a t c h E x c e p t i o n % 186 % % 187 % % 188 % % 189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 190 % 191 % CatchException() returns if no exceptions is found otherwise it reports 192 % the exception as a warning, error, or fatal depending on the severity. 193 % 194 % The format of the CatchException method is: 195 % 196 % CatchException(ExceptionInfo *exception) 197 % 198 % A description of each parameter follows: 199 % 200 % o exception: the exception info. 201 % 202 */ 203 MagickExport void CatchException(ExceptionInfo *exception) 204 { 205 LinkedListInfo 206 *exceptions; 207 208 register const ExceptionInfo 209 *p; 210 211 ssize_t 212 i; 213 214 assert(exception != (ExceptionInfo *) NULL); 215 assert(exception->signature == MagickCoreSignature); 216 if (exception->exceptions == (void *) NULL) 217 return; 218 LockSemaphoreInfo(exception->semaphore); 219 exceptions=(LinkedListInfo *) exception->exceptions; 220 ResetLinkedListIterator(exceptions); 221 p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions); 222 for (i=0; p != (const ExceptionInfo *) NULL; i++) 223 { 224 if ((p->severity >= WarningException) && (p->severity < ErrorException)) 225 MagickWarning(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 >= FatalErrorException) 229 MagickFatalError(p->severity,p->reason,p->description); 230 p=(const ExceptionInfo *) GetNextValueInLinkedList(exceptions); 231 } 232 UnlockSemaphoreInfo(exception->semaphore); 233 ClearMagickException(exception); 234 } 235 236 /* 238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 239 % % 240 % % 241 % % 242 % C l o n e E x c e p t i o n I n f o % 243 % % 244 % % 245 % % 246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 247 % 248 % CloneExceptionInfo() clones the ExceptionInfo structure. 249 % 250 % The format of the CloneExceptionInfo method is: 251 % 252 % ExceptionInfo *CloneException(ExceptionInfo *exception) 253 % 254 % A description of each parameter follows: 255 % 256 % o exception: the exception info. 257 % 258 */ 259 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception) 260 { 261 ExceptionInfo 262 *clone_exception; 263 264 clone_exception=(ExceptionInfo *) AcquireCriticalMemory(sizeof(*exception)); 265 InitializeExceptionInfo(clone_exception); 266 InheritException(clone_exception,exception); 267 clone_exception->relinquish=MagickTrue; 268 return(clone_exception); 269 } 270 271 /* 273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 274 % % 275 % % 276 % % 277 + D e f a u l t E r r o r H a n d l e r % 278 % % 279 % % 280 % % 281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 282 % 283 % DefaultErrorHandler() displays an error reason. 284 % 285 % The format of the DefaultErrorHandler method is: 286 % 287 % void MagickError(const ExceptionType severity,const char *reason, 288 % const char *description) 289 % 290 % A description of each parameter follows: 291 % 292 % o severity: Specifies the numeric error category. 293 % 294 % o reason: Specifies the reason to display before terminating the 295 % program. 296 % 297 % o description: Specifies any description to the reason. 298 % 299 */ 300 static void DefaultErrorHandler(const ExceptionType magick_unused(severity), 301 const char *reason,const char *description) 302 { 303 magick_unreferenced(severity); 304 305 if (reason == (char *) NULL) 306 return; 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); 312 } 313 314 /* 316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 317 % % 318 % % 319 % % 320 + D e f a u l t F a t a l E r r o r H a n d l e r % 321 % % 322 % % 323 % % 324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 325 % 326 % DefaultFatalErrorHandler() displays an error reason and then terminates the 327 % program. 328 % 329 % The format of the DefaultFatalErrorHandler method is: 330 % 331 % void MagickFatalError(const ExceptionType severity,const char *reason, 332 % const char *description) 333 % 334 % A description of each parameter follows: 335 % 336 % o severity: Specifies the numeric error category. 337 % 338 % o reason: Specifies the reason to display before terminating the program. 339 % 340 % o description: Specifies any description to the reason. 341 % 342 */ 343 static void DefaultFatalErrorHandler(const ExceptionType severity, 344 const char *reason,const char *description) 345 { 346 if (reason == (char *) NULL) 347 return; 348 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason); 349 if (description != (char *) NULL) 350 (void) FormatLocaleFile(stderr," (%s)",description); 351 (void) FormatLocaleFile(stderr,".\n"); 352 (void) fflush(stderr); 353 MagickCoreTerminus(); 354 exit((int) (severity-FatalErrorException)+1); 355 } 356 357 /* 359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 360 % % 361 % % 362 % % 363 + D e f a u l t W a r n i n g H a n d l e r % 364 % % 365 % % 366 % % 367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 368 % 369 % DefaultWarningHandler() displays a warning reason. 370 % 371 % The format of the DefaultWarningHandler method is: 372 % 373 % void DefaultWarningHandler(const ExceptionType severity, 374 % const char *reason,const char *description) 375 % 376 % A description of each parameter follows: 377 % 378 % o severity: Specifies the numeric warning category. 379 % 380 % o reason: Specifies the reason to display before terminating the 381 % program. 382 % 383 % o description: Specifies any description to the reason. 384 % 385 */ 386 static void DefaultWarningHandler(const ExceptionType magick_unused(severity), 387 const char *reason,const char *description) 388 { 389 magick_unreferenced(severity); 390 391 if (reason == (char *) NULL) 392 return; 393 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason); 394 if (description != (char *) NULL) 395 (void) FormatLocaleFile(stderr," (%s)",description); 396 (void) FormatLocaleFile(stderr,".\n"); 397 (void) fflush(stderr); 398 } 399 400 /* 402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 403 % % 404 % % 405 % % 406 % D e s t r o y E x c e p t i o n I n f o % 407 % % 408 % % 409 % % 410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 411 % 412 % DestroyExceptionInfo() deallocates memory associated with an exception. 413 % 414 % The format of the DestroyExceptionInfo method is: 415 % 416 % ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception) 417 % 418 % A description of each parameter follows: 419 % 420 % o exception: the exception info. 421 % 422 */ 423 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception) 424 { 425 MagickBooleanType 426 relinquish; 427 428 assert(exception != (ExceptionInfo *) NULL); 429 assert(exception->signature == MagickCoreSignature); 430 if (exception->semaphore == (SemaphoreInfo *) NULL) 431 ActivateSemaphoreInfo(&exception->semaphore); 432 LockSemaphoreInfo(exception->semaphore); 433 exception->severity=UndefinedException; 434 if (exception->relinquish != MagickFalse) 435 { 436 exception->signature=(~MagickCoreSignature); 437 if (exception->exceptions != (void *) NULL) 438 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *) 439 exception->exceptions,DestroyExceptionElement); 440 } 441 else 442 if (exception->exceptions != (void *) NULL) 443 ClearLinkedList((LinkedListInfo *) exception->exceptions, 444 DestroyExceptionElement); 445 relinquish=exception->relinquish; 446 UnlockSemaphoreInfo(exception->semaphore); 447 if (relinquish != MagickFalse) 448 { 449 RelinquishSemaphoreInfo(&exception->semaphore); 450 exception=(ExceptionInfo *) RelinquishMagickMemory(exception); 451 } 452 return(exception); 453 } 454 455 /* 457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 458 % % 459 % % 460 % % 461 % G e t E x c e p t i o n M e s s a g e % 462 % % 463 % % 464 % % 465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 466 % 467 % GetExceptionMessage() returns the error message defined by the specified 468 % error code. 469 % 470 % The format of the GetExceptionMessage method is: 471 % 472 % char *GetExceptionMessage(const int error) 473 % 474 % A description of each parameter follows: 475 % 476 % o error: the error code. 477 % 478 */ 479 MagickExport char *GetExceptionMessage(const int error) 480 { 481 char 482 exception[MagickPathExtent]; 483 484 *exception='\0'; 485 #if defined(MAGICKCORE_HAVE_STRERROR_R) 486 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P) 487 (void) strerror_r(error,exception,sizeof(exception)); 488 #else 489 (void) CopyMagickString(exception,strerror_r(error,exception, 490 sizeof(exception)),sizeof(exception)); 491 #endif 492 #else 493 (void) CopyMagickString(exception,strerror(error),sizeof(exception)); 494 #endif 495 return(ConstantString(exception)); 496 } 497 498 /* 500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 501 % % 502 % % 503 % % 504 % G e t L o c a l e E x c e p t i o n M e s s a g e % 505 % % 506 % % 507 % % 508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 509 % 510 % GetLocaleExceptionMessage() converts a enumerated exception severity and tag 511 % to a message in the current locale. 512 % 513 % The format of the GetLocaleExceptionMessage method is: 514 % 515 % const char *GetLocaleExceptionMessage(const ExceptionType severity, 516 % const char *tag) 517 % 518 % A description of each parameter follows: 519 % 520 % o severity: the severity of the exception. 521 % 522 % o tag: the message tag. 523 % 524 */ 525 526 static const char *ExceptionSeverityToTag(const ExceptionType severity) 527 { 528 switch (severity) 529 { 530 case ResourceLimitWarning: return("Resource/Limit/Warning/"); 531 case TypeWarning: return("Type/Warning/"); 532 case OptionWarning: return("Option/Warning/"); 533 case DelegateWarning: return("Delegate/Warning/"); 534 case MissingDelegateWarning: return("Missing/Delegate/Warning/"); 535 case CorruptImageWarning: return("Corrupt/Image/Warning/"); 536 case FileOpenWarning: return("File/Open/Warning/"); 537 case BlobWarning: return("Blob/Warning/"); 538 case StreamWarning: return("Stream/Warning/"); 539 case CacheWarning: return("Cache/Warning/"); 540 case CoderWarning: return("Coder/Warning/"); 541 case FilterWarning: return("Filter/Warning/"); 542 case ModuleWarning: return("Module/Warning/"); 543 case DrawWarning: return("Draw/Warning/"); 544 case ImageWarning: return("Image/Warning/"); 545 case WandWarning: return("Wand/Warning/"); 546 case XServerWarning: return("XServer/Warning/"); 547 case MonitorWarning: return("Monitor/Warning/"); 548 case RegistryWarning: return("Registry/Warning/"); 549 case ConfigureWarning: return("Configure/Warning/"); 550 case PolicyWarning: return("Policy/Warning/"); 551 case ResourceLimitError: return("Resource/Limit/Error/"); 552 case TypeError: return("Type/Error/"); 553 case OptionError: return("Option/Error/"); 554 case DelegateError: return("Delegate/Error/"); 555 case MissingDelegateError: return("Missing/Delegate/Error/"); 556 case CorruptImageError: return("Corrupt/Image/Error/"); 557 case FileOpenError: return("File/Open/Error/"); 558 case BlobError: return("Blob/Error/"); 559 case StreamError: return("Stream/Error/"); 560 case CacheError: return("Cache/Error/"); 561 case CoderError: return("Coder/Error/"); 562 case FilterError: return("Filter/Error/"); 563 case ModuleError: return("Module/Error/"); 564 case DrawError: return("Draw/Error/"); 565 case ImageError: return("Image/Error/"); 566 case WandError: return("Wand/Error/"); 567 case XServerError: return("XServer/Error/"); 568 case MonitorError: return("Monitor/Error/"); 569 case RegistryError: return("Registry/Error/"); 570 case ConfigureError: return("Configure/Error/"); 571 case PolicyError: return("Policy/Error/"); 572 case ResourceLimitFatalError: return("Resource/Limit/FatalError/"); 573 case TypeFatalError: return("Type/FatalError/"); 574 case OptionFatalError: return("Option/FatalError/"); 575 case DelegateFatalError: return("Delegate/FatalError/"); 576 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/"); 577 case CorruptImageFatalError: return("Corrupt/Image/FatalError/"); 578 case FileOpenFatalError: return("File/Open/FatalError/"); 579 case BlobFatalError: return("Blob/FatalError/"); 580 case StreamFatalError: return("Stream/FatalError/"); 581 case CacheFatalError: return("Cache/FatalError/"); 582 case CoderFatalError: return("Coder/FatalError/"); 583 case FilterFatalError: return("Filter/FatalError/"); 584 case ModuleFatalError: return("Module/FatalError/"); 585 case DrawFatalError: return("Draw/FatalError/"); 586 case ImageFatalError: return("Image/FatalError/"); 587 case WandFatalError: return("Wand/FatalError/"); 588 case XServerFatalError: return("XServer/FatalError/"); 589 case MonitorFatalError: return("Monitor/FatalError/"); 590 case RegistryFatalError: return("Registry/FatalError/"); 591 case ConfigureFatalError: return("Configure/FatalError/"); 592 case PolicyFatalError: return("Policy/FatalError/"); 593 default: break; 594 } 595 return(""); 596 } 597 598 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity, 599 const char *tag) 600 { 601 char 602 message[MagickPathExtent]; 603 604 const char 605 *locale_message; 606 607 assert(tag != (const char *) NULL); 608 (void) FormatLocaleString(message,MagickPathExtent,"Exception/%s%s", 609 ExceptionSeverityToTag(severity),tag); 610 locale_message=GetLocaleMessage(message); 611 if (locale_message == (const char *) NULL) 612 return(tag); 613 if (locale_message == message) 614 return(tag); 615 return(locale_message); 616 } 617 618 /* 620 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 621 % % 622 % % 623 % % 624 % I n h e r i t E x c e p t i o n % 625 % % 626 % % 627 % % 628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 629 % 630 % InheritException() inherits an exception from a related exception. 631 % 632 % The format of the InheritException method is: 633 % 634 % InheritException(ExceptionInfo *exception,const ExceptionInfo *relative) 635 % 636 % A description of each parameter follows: 637 % 638 % o exception: the exception info. 639 % 640 % o relative: the related exception info. 641 % 642 */ 643 MagickExport void InheritException(ExceptionInfo *exception, 644 const ExceptionInfo *relative) 645 { 646 register const ExceptionInfo 647 *p; 648 649 assert(exception != (ExceptionInfo *) NULL); 650 assert(exception->signature == MagickCoreSignature); 651 assert(relative != (ExceptionInfo *) NULL); 652 assert(relative->signature == MagickCoreSignature); 653 assert(exception != relative); 654 if (relative->exceptions == (void *) NULL) 655 return; 656 LockSemaphoreInfo(relative->semaphore); 657 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions); 658 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 659 relative->exceptions); 660 while (p != (const ExceptionInfo *) NULL) 661 { 662 (void) ThrowException(exception,p->severity,p->reason,p->description); 663 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 664 relative->exceptions); 665 } 666 UnlockSemaphoreInfo(relative->semaphore); 667 } 668 669 /* 671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 672 % % 673 % % 674 % % 675 % I n i t i a l i z e t E x c e p t i o n I n f o % 676 % % 677 % % 678 % % 679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 680 % 681 % InitializeExceptionInfo() initializes an exception to default values. 682 % 683 % The format of the InitializeExceptionInfo method is: 684 % 685 % InitializeExceptionInfo(ExceptionInfo *exception) 686 % 687 % A description of each parameter follows: 688 % 689 % o exception: the exception info. 690 % 691 */ 692 MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception) 693 { 694 assert(exception != (ExceptionInfo *) NULL); 695 (void) memset(exception,0,sizeof(*exception)); 696 exception->severity=UndefinedException; 697 exception->exceptions=(void *) NewLinkedList(0); 698 exception->semaphore=AcquireSemaphoreInfo(); 699 exception->signature=MagickCoreSignature; 700 } 701 702 /* 704 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 705 % % 706 % % 707 % % 708 % M a g i c k E r r o r % 709 % % 710 % % 711 % % 712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 713 % 714 % MagickError() calls the exception handler methods with an error reason. 715 % 716 % The format of the MagickError method is: 717 % 718 % void MagickError(const ExceptionType error,const char *reason, 719 % const char *description) 720 % 721 % A description of each parameter follows: 722 % 723 % o exception: Specifies the numeric error category. 724 % 725 % o reason: Specifies the reason to display before terminating the 726 % program. 727 % 728 % o description: Specifies any description to the reason. 729 % 730 */ 731 MagickExport void MagickError(const ExceptionType error,const char *reason, 732 const char *description) 733 { 734 if (error_handler != (ErrorHandler) NULL) 735 (*error_handler)(error,reason,description); 736 } 737 738 /* 740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 741 % % 742 % % 743 % % 744 % M a g i c k F a t al E r r o r % 745 % % 746 % % 747 % % 748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 749 % 750 % MagickFatalError() calls the fatal exception handler methods with an error 751 % reason. 752 % 753 % The format of the MagickError method is: 754 % 755 % void MagickFatalError(const ExceptionType error,const char *reason, 756 % const char *description) 757 % 758 % A description of each parameter follows: 759 % 760 % o exception: Specifies the numeric error category. 761 % 762 % o reason: Specifies the reason to display before terminating the 763 % program. 764 % 765 % o description: Specifies any description to the reason. 766 % 767 */ 768 MagickExport void MagickFatalError(const ExceptionType error,const char *reason, 769 const char *description) 770 { 771 if (fatal_error_handler != (ErrorHandler) NULL) 772 (*fatal_error_handler)(error,reason,description); 773 } 774 775 /* 777 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 778 % % 779 % % 780 % % 781 % M a g i c k W a r n i n g % 782 % % 783 % % 784 % % 785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 786 % 787 % MagickWarning() calls the warning handler methods with a warning reason. 788 % 789 % The format of the MagickWarning method is: 790 % 791 % void MagickWarning(const ExceptionType warning,const char *reason, 792 % const char *description) 793 % 794 % A description of each parameter follows: 795 % 796 % o warning: the warning severity. 797 % 798 % o reason: Define the reason for the warning. 799 % 800 % o description: Describe the warning. 801 % 802 */ 803 MagickExport void MagickWarning(const ExceptionType warning,const char *reason, 804 const char *description) 805 { 806 if (warning_handler != (WarningHandler) NULL) 807 (*warning_handler)(warning,reason,description); 808 } 809 810 /* 812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 813 % % 814 % % 815 % % 816 % S e t E r r o r H a n d l e r % 817 % % 818 % % 819 % % 820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 821 % 822 % SetErrorHandler() sets the exception handler to the specified method 823 % and returns the previous exception handler. 824 % 825 % The format of the SetErrorHandler method is: 826 % 827 % ErrorHandler SetErrorHandler(ErrorHandler handler) 828 % 829 % A description of each parameter follows: 830 % 831 % o handler: the method to handle errors. 832 % 833 */ 834 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler) 835 { 836 ErrorHandler 837 previous_handler; 838 839 previous_handler=error_handler; 840 error_handler=handler; 841 return(previous_handler); 842 } 843 844 /* 846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 847 % % 848 % % 849 % % 850 % S e t F a t a l E r r o r H a n d l e r % 851 % % 852 % % 853 % % 854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 855 % 856 % SetFatalErrorHandler() sets the fatal exception handler to the specified 857 % method and returns the previous fatal exception handler. 858 % 859 % The format of the SetErrorHandler method is: 860 % 861 % ErrorHandler SetErrorHandler(ErrorHandler handler) 862 % 863 % A description of each parameter follows: 864 % 865 % o handler: the method to handle errors. 866 % 867 */ 868 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler) 869 { 870 FatalErrorHandler 871 previous_handler; 872 873 previous_handler=fatal_error_handler; 874 fatal_error_handler=handler; 875 return(previous_handler); 876 } 877 878 /* 880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 881 % % 882 % % 883 % % 884 % S e t W a r n i n g H a n d l e r % 885 % % 886 % % 887 % % 888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 889 % 890 % SetWarningHandler() sets the warning handler to the specified method 891 % and returns the previous warning handler. 892 % 893 % The format of the SetWarningHandler method is: 894 % 895 % ErrorHandler SetWarningHandler(ErrorHandler handler) 896 % 897 % A description of each parameter follows: 898 % 899 % o handler: the method to handle warnings. 900 % 901 */ 902 MagickExport WarningHandler SetWarningHandler(WarningHandler handler) 903 { 904 WarningHandler 905 previous_handler; 906 907 previous_handler=warning_handler; 908 warning_handler=handler; 909 return(previous_handler); 910 } 911 912 /* 914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 915 % % 916 % % 917 % % 918 % T h r o w E x c e p t i o n % 919 % % 920 % % 921 % % 922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 923 % 924 % ThrowException() throws an exception with the specified severity code, 925 % reason, and optional description. 926 % 927 % The format of the ThrowException method is: 928 % 929 % MagickBooleanType ThrowException(ExceptionInfo *exception, 930 % const ExceptionType severity,const char *reason, 931 % const char *description) 932 % 933 % A description of each parameter follows: 934 % 935 % o exception: the exception info. 936 % 937 % o severity: the severity of the exception. 938 % 939 % o reason: the reason for the exception. 940 % 941 % o description: the exception description. 942 % 943 */ 944 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception, 945 const ExceptionType severity,const char *reason,const char *description) 946 { 947 LinkedListInfo 948 *exceptions; 949 950 register ExceptionInfo 951 *p; 952 953 assert(exception != (ExceptionInfo *) NULL); 954 assert(exception->signature == MagickCoreSignature); 955 LockSemaphoreInfo(exception->semaphore); 956 exceptions=(LinkedListInfo *) exception->exceptions; 957 if (GetNumberOfElementsInLinkedList(exceptions) > MaxExceptionList) 958 { 959 if (severity < ErrorException) 960 { 961 UnlockSemaphoreInfo(exception->semaphore); 962 return(MagickTrue); 963 } 964 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions); 965 if (p->severity >= ErrorException) 966 { 967 UnlockSemaphoreInfo(exception->semaphore); 968 return(MagickTrue); 969 } 970 } 971 p=(ExceptionInfo *) GetLastValueInLinkedList(exceptions); 972 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) && 973 (LocaleCompare(exception->reason,reason) == 0) && 974 (LocaleCompare(exception->description,description) == 0)) 975 { 976 UnlockSemaphoreInfo(exception->semaphore); 977 return(MagickTrue); 978 } 979 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p)); 980 if (p == (ExceptionInfo *) NULL) 981 { 982 UnlockSemaphoreInfo(exception->semaphore); 983 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 984 } 985 (void) memset(p,0,sizeof(*p)); 986 p->severity=severity; 987 if (reason != (const char *) NULL) 988 p->reason=ConstantString(reason); 989 if (description != (const char *) NULL) 990 p->description=ConstantString(description); 991 p->signature=MagickCoreSignature; 992 (void) AppendValueToLinkedList(exceptions,p); 993 if (p->severity > exception->severity) 994 { 995 exception->severity=p->severity; 996 exception->reason=p->reason; 997 exception->description=p->description; 998 } 999 UnlockSemaphoreInfo(exception->semaphore); 1000 if (GetNumberOfElementsInLinkedList(exceptions) == MaxExceptionList) 1001 (void) ThrowMagickException(exception,GetMagickModule(), 1002 ResourceLimitWarning,"TooManyExceptions", 1003 "(exception processing is suspended)"); 1004 return(MagickTrue); 1005 } 1006 1007 /* 1009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1010 % % 1011 % % 1012 % % 1013 % T h r o w M a g i c k E x c e p t i o n % 1014 % % 1015 % % 1016 % % 1017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1018 % 1019 % ThrowMagickException logs an exception as determined by the log 1020 % configuration file. If an error occurs, MagickFalse is returned 1021 % otherwise MagickTrue. 1022 % 1023 % The format of the ThrowMagickException method is: 1024 % 1025 % MagickBooleanType ThrowFileException(ExceptionInfo *exception, 1026 % const char *module,const char *function,const size_t line, 1027 % const ExceptionType severity,const char *tag,const char *format,...) 1028 % 1029 % A description of each parameter follows: 1030 % 1031 % o exception: the exception info. 1032 % 1033 % o filename: the source module filename. 1034 % 1035 % o function: the function name. 1036 % 1037 % o line: the line number of the source module. 1038 % 1039 % o severity: Specifies the numeric error category. 1040 % 1041 % o tag: the locale tag. 1042 % 1043 % o format: the output format. 1044 % 1045 */ 1046 1047 MagickExport MagickBooleanType ThrowMagickExceptionList( 1048 ExceptionInfo *exception,const char *module,const char *function, 1049 const size_t line,const ExceptionType severity,const char *tag, 1050 const char *format,va_list operands) 1051 { 1052 char 1053 message[MagickPathExtent], 1054 path[MagickPathExtent], 1055 reason[MagickPathExtent]; 1056 1057 const char 1058 *locale, 1059 *type; 1060 1061 int 1062 n; 1063 1064 MagickBooleanType 1065 status; 1066 1067 size_t 1068 length; 1069 1070 assert(exception != (ExceptionInfo *) NULL); 1071 assert(exception->signature == MagickCoreSignature); 1072 locale=GetLocaleExceptionMessage(severity,tag); 1073 (void) CopyMagickString(reason,locale,MagickPathExtent); 1074 (void) ConcatenateMagickString(reason," ",MagickPathExtent); 1075 length=strlen(reason); 1076 #if defined(MAGICKCORE_HAVE_VSNPRINTF) 1077 n=vsnprintf(reason+length,MagickPathExtent-length,format,operands); 1078 #else 1079 n=vsprintf(reason+length,format,operands); 1080 #endif 1081 if (n < 0) 1082 reason[MagickPathExtent-1]='\0'; 1083 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason); 1084 GetPathComponent(module,TailPath,path); 1085 type="undefined"; 1086 if ((severity >= WarningException) && (severity < ErrorException)) 1087 type="warning"; 1088 if ((severity >= ErrorException) && (severity < FatalErrorException)) 1089 type="error"; 1090 if (severity >= FatalErrorException) 1091 type="fatal"; 1092 (void) FormatLocaleString(message,MagickPathExtent,"%s @ %s/%s/%s/%.20g", 1093 reason,type,path,function,(double) line); 1094 (void) ThrowException(exception,severity,message,(char *) NULL); 1095 return(status); 1096 } 1097 1098 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, 1099 const char *module,const char *function,const size_t line, 1100 const ExceptionType severity,const char *tag,const char *format,...) 1101 { 1102 MagickBooleanType 1103 status; 1104 1105 va_list 1106 operands; 1107 1108 va_start(operands,format); 1109 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag, 1110 format,operands); 1111 va_end(operands); 1112 return(status); 1113 } 1114