1 /*
2 % Copyright (C) 2003-2019 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
5 %
6 % This program is covered by multiple licenses, which are described in
7 % Copyright.txt. You should have received a copy of Copyright.txt with this
8 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9 %
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11 % %
12 % %
13 % %
14 % EEEEE RRRR RRRR OOO RRRR %
15 % E R R R R O O R R %
16 % EEE RRRR RRRR O O RRRR %
17 % E R R R R O O R R %
18 % EEEEE R R R R OOO R R %
19 % %
20 % %
21 % GraphicsMagick Exception Methods %
22 % %
23 % %
24 % Software Design %
25 % John Cristy %
26 % July 1993 %
27 % %
28 % %
29 % %
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 %
32 %
33 %
34 */
35
36 /*
37 Include declarations.
38 */
39 #include "magick/studio.h"
40 #include "magick/magick.h"
41 #include "magick/semaphore.h"
42 #include "magick/utility.h"
43
44 /*
45 Forward declarations.
46 */
47 #if defined(__cplusplus) || defined(c_plusplus)
48 extern "C" {
49 #endif
50
51 static void
52 DefaultErrorHandler(const ExceptionType,const char *,const char *),
53 DefaultFatalErrorHandler(const ExceptionType,const char *,const char *) MAGICK_FUNC_NORETURN,
54 DefaultWarningHandler(const ExceptionType,const char *,const char *);
55
56 #if defined(__cplusplus) || defined(c_plusplus)
57 }
58 #endif
59
60 /*
61 Global declarations.
62 */
63 static SemaphoreInfo
64 *error_semaphore = (SemaphoreInfo *) NULL;
65
66 static ErrorHandler
67 error_handler = DefaultErrorHandler;
68
69 static FatalErrorHandler
70 fatal_error_handler = DefaultFatalErrorHandler;
71
72 static WarningHandler
73 warning_handler = DefaultWarningHandler;
74
75 /*
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 % %
78 % %
79 % %
80 + I n i t i a l i z e M a g i c k E x c e p t i o n H a n d l i n g %
81 % %
82 % %
83 % %
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 %
86 % Method InitializeMagickExceptionHandling initializes the exception
87 % reporting facility so that exception reporting is thread safe.
88 % This function must be invoked before any exception is thrown.
89 % A memory-allocation failure in this function results in a fatal
90 % error for the whole program. All of the allocations performed by
91 % this function are released by DestroyMagickExceptionHandling().
92 %
93 % The format of the InitializeLogInfo method is:
94 %
95 % MagickPassFail InitializeLogInfo(void)
96 %
97 %
98 */
99 MagickPassFail
InitializeMagickExceptionHandling(void)100 InitializeMagickExceptionHandling(void)
101 {
102 /*
103 Initialize error-reporting semaphore
104 */
105 assert(error_semaphore == (SemaphoreInfo *) NULL);
106 error_semaphore=AllocateSemaphoreInfo();
107 return MagickPass;
108 }
109
110 /*
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 % %
113 % %
114 % %
115 + D e s t r o y M a g i c k E x c e p t i o n H a n d l i n g %
116 % %
117 % %
118 % %
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %
121 % Method DestroyMagickExceptionHandling deallocates resources allocated
122 % for exception handling.
123 %
124 % The format of the DestroyLogInfo method is:
125 %
126 % DestroyLogInfo(void)
127 %
128 %
129 */
DestroyMagickExceptionHandling(void)130 void DestroyMagickExceptionHandling(void)
131 {
132 /*
133 Destroy error-reporting semaphore
134 */
135 DestroySemaphoreInfo(&error_semaphore);
136 }
137
138 /*
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 % %
141 % %
142 % %
143 % C a t c h E x c e p t i o n %
144 % %
145 % %
146 % %
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 %
149 % CatchException() returns if no exceptions is found otherwise it reports
150 % the exception as a warning, error, or fatal depending on the severity.
151 %
152 % The format of the CatchException method is:
153 %
154 % CatchException(const ExceptionInfo *exception)
155 %
156 % A description of each parameter follows:
157 %
158 % o exception: The exception info.
159 %
160 %
161 */
CatchException(const ExceptionInfo * exception)162 MagickExport void CatchException(const ExceptionInfo *exception)
163 {
164 assert(exception != (ExceptionInfo *) NULL);
165 assert(exception->signature == MagickSignature);
166
167 do
168 {
169 if (exception->severity == UndefinedException)
170 break;
171 errno=exception->error_number; /* Shabby work-around for parameter limits */
172 if ((exception->severity >= WarningException) &&
173 (exception->severity < ErrorException))
174 {
175 MagickWarning2(exception->severity,exception->reason,
176 exception->description);
177 break;
178 }
179 if ((exception->severity >= ErrorException) &&
180 (exception->severity < FatalErrorException))
181 {
182 MagickError2(exception->severity,exception->reason,exception->description);
183 break;
184 }
185 if (exception->severity >= FatalErrorException)
186 {
187 MagickFatalError2(exception->severity,exception->reason,
188 exception->description);
189 break;
190 }
191 } while(0);
192 }
193
194 /*
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 % %
197 % %
198 % %
199 % C o p y E x c e p t i o n %
200 % %
201 % %
202 % %
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 %
205 % CopyException() copies exception data from one ExceptionInfo structure
206 % to another.
207 %
208 % The format of the CopyException method is:
209 %
210 % void CopyException(ExceptionInfo *copy, const ExceptionInfo *original)
211 %
212 % A description of each parameter follows:
213 %
214 % o copy: The exception to copy to.
215 %
216 % o original: The exception to copy from.
217 %
218 */
CopyException(ExceptionInfo * copy,const ExceptionInfo * original)219 MagickExport void CopyException(ExceptionInfo *copy, const ExceptionInfo *original)
220 {
221 assert(copy != (ExceptionInfo *) NULL);
222 assert(copy->signature == MagickSignature);
223 assert(original != (ExceptionInfo *) NULL);
224 assert(copy != original);
225 assert(original->signature == MagickSignature);
226 copy->severity=original->severity;
227 MagickFreeMemory(copy->reason);
228 if (original->reason)
229 copy->reason=AcquireString(original->reason);
230 MagickFreeMemory(copy->description);
231 if (original->description)
232 copy->description=AcquireString(original->description);
233 copy->error_number=original->error_number;
234 MagickFreeMemory(copy->module);
235 if (original->module)
236 copy->module=AcquireString(original->module);
237 MagickFreeMemory(copy->function);
238 if (original->function)
239 copy->function=AcquireString(original->function);
240 copy->line=original->line;
241 return;
242 }
243
244 /*
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 % %
247 % %
248 % %
249 + D e f a u l t E r r o r H a n d l e r %
250 % %
251 % %
252 % %
253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 %
255 % Method DefaultErrorHandler displays an error reason.
256 %
257 % The format of the DefaultErrorHandler method is:
258 %
259 % void DefaultMagickError(const ExceptionType severity,
260 % const char *reason, const char *description)
261 %
262 % A description of each parameter follows:
263 %
264 % o severity: Specifies the numeric error category.
265 %
266 % o reason: Specifies the reason to display before terminating the
267 % program.
268 %
269 % o description: Specifies any description to the reason.
270 %
271 %
272 */
273
GetErrorMessageString(const int error_number)274 static const char *GetErrorMessageString(const int error_number)
275 {
276 const char
277 *message;
278
279 message=strerror(error_number);
280 if (message == (const char *) NULL)
281 return("Error number is out of range");
282 return(message);
283 }
284
DefaultErrorHandler(const ExceptionType severity,const char * reason,const char * description)285 static void DefaultErrorHandler(const ExceptionType severity,const char *reason,
286 const char *description)
287 {
288 if (reason == (char *) NULL)
289 return;
290
291 (void) fprintf(stderr,"%.1024s: ",GetClientName());
292 if (strstr(reason,"%s") && description)
293 {
294 /*
295 Reason contains printf specification. %s in reason string
296 is substituted with description.
297 */
298 (void) fprintf(stderr,reason,description);
299 }
300 else
301 {
302 (void) fprintf(stderr,"%.1024s",reason);
303 if (description != (char *) NULL)
304 (void) fprintf(stderr," (%.1024s)",description);
305 }
306 /*
307 FIXME: The following captures a random errno value rather than the
308 errno associated with the actual error.
309 */
310 if ((severity != OptionError) && errno)
311 (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
312 (void) fprintf(stderr,".\n");
313 }
314
315 /*
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 % Method DefaultFatalErrorHandler displays an error reason and then terminates
327 % the program.
328 %
329 % The format of the DefaultFatalErrorHandler method is:
330 %
331 % void DefaultMagickFatalError(const ExceptionType severity,
332 % const char *reason, 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
339 % program.
340 %
341 % o description: Specifies any description to the reason.
342 %
343 %
344 */
DefaultFatalErrorHandler(const ExceptionType severity,const char * reason,const char * description)345 static void DefaultFatalErrorHandler(const ExceptionType severity,
346 const char *reason,const char *description)
347 {
348 if (reason != (char *) NULL)
349 {
350 (void) fprintf(stderr,"%.1024s: %.1024s",GetClientName(),reason);
351 if (description != (char *) NULL)
352 (void) fprintf(stderr," (%.1024s)",description);
353 if ((severity != OptionError) && errno)
354 (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
355 (void) fprintf(stderr,".\n");
356 }
357 /*
358 Release persistent resources
359 */
360 PanicDestroyMagick();
361 /*
362 Program quits
363 */
364 Exit(severity);
365 }
366
367 /*
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % %
370 % %
371 % %
372 + D e f a u l t W a r n i n g H a n d l e r %
373 % %
374 % %
375 % %
376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
377 %
378 % Method DefaultWarningHandler displays a warning reason.
379 %
380 % The format of the DefaultWarningHandler method is:
381 %
382 % void DefaultWarningHandler(const ExceptionType warning,
383 % const char *reason,const char *description)
384 %
385 % A description of each parameter follows:
386 %
387 % o warning: Specifies the numeric warning category.
388 %
389 % o reason: Specifies the reason to display before terminating the
390 % program.
391 %
392 % o description: Specifies any description to the reason.
393 %
394 %
395 */
DefaultWarningHandler(const ExceptionType severity,const char * reason,const char * description)396 static void DefaultWarningHandler(const ExceptionType severity,
397 const char *reason,const char *description)
398 {
399 if (reason == (char *) NULL)
400 return;
401 (void) fprintf(stderr,"%.1024s: %.1024s",GetClientName(),reason);
402 if (description != (char *) NULL)
403 (void) fprintf(stderr," (%.1024s)",description);
404 if ((severity != OptionWarning) && errno)
405 (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
406 (void) fprintf(stderr,".\n");
407 }
408
409 /*
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 % %
412 % %
413 % %
414 % D e s t r o y E x c e p t i o n I n f o %
415 % %
416 % %
417 % %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 %
420 % DestroyExceptionInfo() deallocates memory associated with exception.
421 %
422 % The format of the DestroyExceptionInfo method is:
423 %
424 % void DestroyExceptionInfo(ExceptionInfo *exception)
425 %
426 % A description of each parameter follows:
427 %
428 % o exception: The exception info.
429 %
430 %
431 */
DestroyExceptionInfo(ExceptionInfo * exception)432 MagickExport void DestroyExceptionInfo(ExceptionInfo *exception)
433 {
434 assert(exception != (ExceptionInfo *) NULL);
435 assert(exception->signature == MagickSignature);
436 exception->severity=UndefinedException;
437 MagickFreeMemory(exception->reason);
438 MagickFreeMemory(exception->description);
439 exception->error_number=0;
440 MagickFreeMemory(exception->module);
441 MagickFreeMemory(exception->function);
442 exception->line=0UL;
443 exception->signature=0UL;
444 }
445
446 /*
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 % %
449 % %
450 % %
451 % G e t E x c e p t i o n I n f o %
452 % %
453 % %
454 % %
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 %
457 % GetExceptionInfo() initializes an exception to default values.
458 %
459 % The format of the GetExceptionInfo method is:
460 %
461 % GetExceptionInfo(ExceptionInfo *exception)
462 %
463 % A description of each parameter follows:
464 %
465 % o exception: The exception info.
466 %
467 %
468 */
GetExceptionInfo(ExceptionInfo * exception)469 MagickExport void GetExceptionInfo(ExceptionInfo *exception)
470 {
471 assert(exception != (ExceptionInfo *) NULL);
472 exception->severity=UndefinedException;
473 exception->reason=0;
474 exception->description=0;
475 exception->error_number=0;
476 exception->module=0;
477 exception->function=0;
478 exception->line=0UL;
479 exception->signature=MagickSignature;
480 }
481
482 /*
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 % %
485 % %
486 % %
487 % 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 %
488 % %
489 % %
490 % %
491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 %
493 % GetLocaleExceptionMessage() converts a enumerated exception severity and tag
494 % to a message in the current locale.
495 %
496 % The format of the GetLocaleExceptionMessage method is:
497 %
498 % const char *GetLocaleExceptionMessage(const ExceptionType severity,
499 % const char *tag)
500 %
501 % A description of each parameter follows:
502 %
503 % o severity: the severity of the exception.
504 %
505 % o tag: the message tag.
506 %
507 %
508 %
509 */
510
ExceptionSeverityToTag(const ExceptionType severity)511 static const char *ExceptionSeverityToTag(const ExceptionType severity)
512 {
513 switch (severity)
514 {
515 case UndefinedException: return("Unknown/Error/");
516 case ResourceLimitWarning: return("Resource/Limit/Warning/");
517 case TypeWarning: return("Type/Warning/");
518 case OptionWarning: return("Option/Warning/");
519 case DelegateWarning: return("Delegate/Warning/");
520 case MissingDelegateWarning: return("Missing/Delegate/Warning/");
521 case CorruptImageWarning: return("Corrupt/Image/Warning/");
522 case FileOpenWarning: return("File/Open/Warning/");
523 case BlobWarning: return("Blob/Warning/");
524 case StreamWarning: return("Stream/Warning/");
525 case CacheWarning: return("Cache/Warning/");
526 case CoderWarning: return("Coder/Warning/");
527 case ModuleWarning: return("Module/Warning/");
528 case DrawWarning: return("Draw/Warning/");
529 case ImageWarning: return("Image/Warning/");
530 case WandWarning: return("Wand/Warning/");
531 case XServerWarning: return("XServer/Warning/");
532 case MonitorWarning: return("Monitor/Warning/");
533 case RegistryWarning: return("Registry/Warning/");
534 case ConfigureWarning: return("Configure/Warning/");
535 case ResourceLimitError: return("Resource/Limit/Error/");
536 case TypeError: return("Type/Error/");
537 case OptionError: return("Option/Error/");
538 case DelegateError: return("Delegate/Error/");
539 case MissingDelegateError: return("Missing/Delegate/Error/");
540 case CorruptImageError: return("Corrupt/Image/Error/");
541 case FileOpenError: return("File/Open/Error/");
542 case BlobError: return("Blob/Error/");
543 case StreamError: return("Stream/Error/");
544 case CacheError: return("Cache/Error/");
545 case CoderError: return("Coder/Error/");
546 case ModuleError: return("Module/Error/");
547 case DrawError: return("Draw/Error/");
548 case ImageError: return("Image/Error/");
549 case WandError: return("Wand/Error/");
550 case XServerError: return("XServer/Error/");
551 case MonitorError: return("Monitor/Error/");
552 case RegistryError: return("Registry/Error/");
553 case ConfigureError: return("Configure/Error/");
554 case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
555 case TypeFatalError: return("Type/FatalError/");
556 case OptionFatalError: return("Option/FatalError/");
557 case DelegateFatalError: return("Delegate/FatalError/");
558 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
559 case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
560 case FileOpenFatalError: return("File/Open/FatalError/");
561 case BlobFatalError: return("Blob/FatalError/");
562 case StreamFatalError: return("Stream/FatalError/");
563 case CacheFatalError: return("Cache/FatalError/");
564 case CoderFatalError: return("Coder/FatalError/");
565 case ModuleFatalError: return("Module/FatalError/");
566 case DrawFatalError: return("Draw/FatalError/");
567 case ImageFatalError: return("Image/FatalError/");
568 case WandFatalError: return("Wand/FatalError/");
569 case XServerFatalError: return("XServer/FatalError/");
570 case MonitorFatalError: return("Monitor/FatalError/");
571 case RegistryFatalError: return("Registry/FatalError/");
572 case ConfigureFatalError: return("Configure/FatalError/");
573 default: break;
574 }
575 return("");
576 }
577
GetLocaleExceptionMessage(const ExceptionType severity,const char * tag)578 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
579 const char *tag)
580 {
581 char
582 message[MaxTextExtent];
583
584 const char
585 *locale_message;
586
587 /* protect against NULL lookups */
588 if (tag != (char *) NULL)
589 {
590 /* This is a hack that depends on the fact that tag can never have spaces in
591 them. If a space is found then it means we are being asked to translate a
592 message that has already been translated. A big waste of time. The reason
593 this happens is that messages are translated at the point of an exception
594 and then again when the exception is caught and processed via the default
595 error and warning handlers
596 */
597 if (strrchr(tag, ' '))
598 return tag;
599 FormatString(message,"%.1024s%.1024s",ExceptionSeverityToTag(severity),tag);
600 locale_message=GetLocaleMessage(message);
601 if (locale_message == message)
602 return(tag);
603 return(locale_message);
604 }
605 return(tag);
606 }
607
608 /*
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 % %
611 % %
612 % %
613 % M a g i c k E r r o r %
614 % %
615 % %
616 % %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %
619 % Method MagickError calls the error handler methods with an error reason.
620 %
621 % The format of the MagickError method is:
622 %
623 % void MagickError(const ExceptionType error,const char *reason,
624 % const char *description)
625 %
626 % A description of each parameter follows:
627 %
628 % o exception: Specifies the numeric error category.
629 %
630 % o reason: Specifies the reason to display before terminating the
631 % program.
632 %
633 % o description: Specifies any description to the reason.
634 %
635 %
636 */
637 #if defined(MagickError)
_MagickError(const ExceptionType error,const char * reason,const char * description)638 MagickExport void _MagickError(const ExceptionType error,const char *reason,
639 const char *description)
640 {
641 if (error_handler != (ErrorHandler) NULL)
642 (*error_handler)(error,GetLocaleExceptionMessage(error,reason),
643 GetLocaleExceptionMessage(error,description));
644 }
645 #endif
646 #if !defined(PREFIX_MAGICK_SYMBOLS)
647 #undef MagickError
MagickError(const ExceptionType error,const char * reason,const char * description)648 MagickExport void MagickError(const ExceptionType error,const char *reason,
649 const char *description)
650 {
651 if (error_handler != (ErrorHandler) NULL)
652 (*error_handler)(error,GetLocaleExceptionMessage(error,reason),
653 GetLocaleExceptionMessage(error,description));
654 }
655 #endif
656
657 /*
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 % %
660 % %
661 % %
662 % M a g i c k F a t a l E r r o r %
663 % %
664 % %
665 % %
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %
668 % MagickFatalError() calls the fatal error handler methods with an error
669 % reason. The fatal error handler is not expected to return!
670 %
671 % The format of the MagickFatalError method is:
672 %
673 % void MagickFatalError(const ExceptionType error,const char *reason,
674 % const char *description)
675 %
676 % A description of each parameter follows:
677 %
678 % o exception: Specifies the numeric error category.
679 %
680 % o reason: Specifies the reason to display before terminating the
681 % program.
682 %
683 % o description: Specifies any description to the reason.
684 %
685 %
686 */
687 #if defined(MagickFatalError)
_MagickFatalError(const ExceptionType error,const char * reason,const char * description)688 MagickExport void _MagickFatalError(const ExceptionType error,const char *reason,
689 const char *description)
690 {
691 if (fatal_error_handler != (ErrorHandler) NULL)
692 (*fatal_error_handler)(error,GetLocaleExceptionMessage(error,reason),
693 GetLocaleExceptionMessage(error,description));
694 errno=0;
695 abort();
696 }
697 #endif
698 #if !defined(PREFIX_MAGICK_SYMBOLS)
699 #undef MagickFatalError
MagickFatalError(const ExceptionType error,const char * reason,const char * description)700 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
701 const char *description)
702 {
703 if (fatal_error_handler != (ErrorHandler) NULL)
704 (*fatal_error_handler)(error,GetLocaleExceptionMessage(error,reason),
705 GetLocaleExceptionMessage(error,description));
706 errno=0;
707 abort();
708 }
709 #endif
710
711 /*
712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 % %
714 % %
715 % %
716 % M a g i c k W a r n i n g %
717 % %
718 % %
719 % %
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 %
722 % Method MagickWarning calls the warning handler methods with a warning
723 % reason.
724 %
725 % The format of the MagickWarning method is:
726 %
727 % void MagickWarning(const ExceptionType warning,const char *reason,
728 % const char *description)
729 %
730 % A description of each parameter follows:
731 %
732 % o warning: The warning severity.
733 %
734 % o reason: Define the reason for the warning.
735 %
736 % o description: Describe the warning.
737 %
738 %
739 */
740 #if defined(MagickWarning)
_MagickWarning(const ExceptionType warning,const char * reason,const char * description)741 MagickExport void _MagickWarning(const ExceptionType warning,const char *reason,
742 const char *description)
743 {
744 if (warning_handler != (WarningHandler) NULL)
745 (*warning_handler)(warning,GetLocaleExceptionMessage(warning,reason),
746 GetLocaleExceptionMessage(warning,description));
747 }
748 #endif
749 #if !defined(PREFIX_MAGICK_SYMBOLS)
750 #undef MagickWarning
MagickWarning(const ExceptionType warning,const char * reason,const char * description)751 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
752 const char *description)
753 {
754 if (warning_handler != (WarningHandler) NULL)
755 (*warning_handler)(warning,GetLocaleExceptionMessage(warning,reason),
756 GetLocaleExceptionMessage(warning,description));
757 }
758 #endif
759
760 /*
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 % %
763 % %
764 % %
765 % S e t E r r o r H a n d l e r %
766 % %
767 % %
768 % %
769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 %
771 % SetErrorHandler() sets the error handler to the specified method
772 % and returns the previous error handler.
773 %
774 % The format of the SetErrorHandler method is:
775 %
776 % ErrorHandler SetErrorHandler(ErrorHandler handler)
777 %
778 % A description of each parameter follows:
779 %
780 % o handler: The method to handle errors.
781 %
782 %
783 */
SetErrorHandler(ErrorHandler handler)784 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
785 {
786 ErrorHandler
787 previous_handler;
788
789 LockSemaphoreInfo(error_semaphore);
790 previous_handler=error_handler;
791 error_handler=handler;
792 UnlockSemaphoreInfo(error_semaphore);
793 return(previous_handler);
794 }
795
796 /*
797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798 % %
799 % %
800 % %
801 % S e t E x c e p t i o n I n f o %
802 % %
803 % %
804 % %
805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 %
807 % SetExceptionInfo() set the exception severity.
808 %
809 % The format of the SetExceptionInfo method is:
810 %
811 % SetExceptionInfo(ExceptionInfo *exception,ExceptionType severity)
812 %
813 % A description of each parameter follows:
814 %
815 % o exception: The exception info.
816 %
817 % o severity: The exception severity.
818 %
819 %
820 */
SetExceptionInfo(ExceptionInfo * exception,ExceptionType severity)821 MagickExport void SetExceptionInfo(ExceptionInfo *exception,
822 ExceptionType severity)
823 {
824 assert(exception != (ExceptionInfo *) NULL);
825 LockSemaphoreInfo(error_semaphore);
826 exception->severity=severity;
827 errno=0;
828 UnlockSemaphoreInfo(error_semaphore);
829 }
830
831 /*
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % %
834 % %
835 % %
836 % S e t F a t a l E r r o r H a n d l e r %
837 % %
838 % %
839 % %
840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 %
842 % SetFatalErrorHandler() sets the fatal error handler to the specified method
843 % and returns the previous fatal error handler.
844 %
845 % The format of the SetFatalErrorHandler method is:
846 %
847 % FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
848 %
849 % A description of each parameter follows:
850 %
851 % o handler: The method to handle errors.
852 %
853 %
854 */
SetFatalErrorHandler(FatalErrorHandler handler)855 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
856 {
857 FatalErrorHandler
858 previous_handler;
859
860 LockSemaphoreInfo(error_semaphore);
861 previous_handler=fatal_error_handler;
862 fatal_error_handler=handler;
863 UnlockSemaphoreInfo(error_semaphore);
864 return(previous_handler);
865 }
866
867 /*
868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 % %
870 % %
871 % %
872 % S e t W a r n i n g H a n d l e r %
873 % %
874 % %
875 % %
876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877 %
878 % SetWarningHandler() sets the warning handler to the specified method
879 % and returns the previous warning handler.
880 %
881 % The format of the SetWarningHandler method is:
882 %
883 % ErrorHandler SetWarningHandler(ErrorHandler handler)
884 %
885 % A description of each parameter follows:
886 %
887 % o handler: The method to handle warnings.
888 %
889 %
890 */
SetWarningHandler(WarningHandler handler)891 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
892 {
893 WarningHandler
894 previous_handler;
895
896 LockSemaphoreInfo(error_semaphore);
897 previous_handler=warning_handler;
898 warning_handler=handler;
899 UnlockSemaphoreInfo(error_semaphore);
900 return(previous_handler);
901 }
902
903 /*
904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 % %
906 % %
907 % %
908 % T h r o w E x c e p t i o n %
909 % %
910 % %
911 % %
912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913 %
914 % ThrowException() throws an exception with the specified severity code,
915 % reason, and optional description.
916 %
917 % The format of the ThrowException method is:
918 %
919 % void ThrowException(ExceptionInfo *exception,
920 % const ExceptionType severity,const char *reason,
921 % const char *description)
922 %
923 % A description of each parameter follows:
924 %
925 % o exception: The exception.
926 %
927 % o severity: The severity of the exception.
928 %
929 % o reason: The reason of the exception.
930 %
931 % o description: The exception description.
932 %
933 %
934 */
935 #if !defined(PREFIX_MAGICK_SYMBOLS)
936 #undef ThrowException
ThrowException(ExceptionInfo * exception,const ExceptionType severity,const char * reason,const char * description)937 MagickExport void ThrowException(ExceptionInfo *exception,
938 const ExceptionType severity,const char *reason,const char *description)
939 {
940 const int orig_errno=errno;
941 assert(exception != (ExceptionInfo *) NULL);
942 assert(exception->signature == MagickSignature);
943 LockSemaphoreInfo(error_semaphore);
944 exception->severity=(ExceptionType) severity;
945 {
946 char *new_reason=NULL;
947 if (reason)
948 new_reason=AcquireString(GetLocaleExceptionMessage(severity,reason));
949 MagickFreeMemory(exception->reason);
950 exception->reason=new_reason;
951 }
952 {
953 char *new_description=NULL;
954 if (description)
955 new_description=
956 AcquireString(GetLocaleExceptionMessage(severity,description));
957 MagickFreeMemory(exception->description);
958 exception->description=new_description;
959 }
960 exception->error_number=orig_errno;
961 MagickFreeMemory(exception->module);
962 MagickFreeMemory(exception->function);
963 exception->line=0UL;
964 exception->signature=0UL;
965 UnlockSemaphoreInfo(error_semaphore);
966 return;
967 }
968 #endif
969
970 /*
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 % %
973 % %
974 % %
975 % T h r o w L o g g e d E x c e p t i o n %
976 % %
977 % %
978 % %
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 %
981 % ThrowLoggedException() throws an exception with the specified severity code,
982 % reason, optional description, source filename, function name, and line
983 % number. If logging is enabled, the exception is also logged.
984 %
985 % If the exception already contains an ErrorException (or greater) or the
986 % existing exception is more severe, then it is ignored.
987 %
988 % The format of the ThrowLoggedException method is:
989 %
990 % void ThrowLoggedException(ExceptionInfo *exception,
991 % const ExceptionType severity,const char *reason,
992 % const char *description,const char *module,
993 % const char *function,const unsigned long line
994 %
995 % A description of each parameter follows:
996 %
997 % o exception: The exception.
998 %
999 % o severity: The severity of the exception.
1000 %
1001 % o reason: The reason of the exception.
1002 %
1003 % o description: The exception description.
1004 %
1005 % o filename: The source module filename.
1006 %
1007 % o function: The function name.
1008 %
1009 % o line: The line number of the source module.
1010 %
1011 %
1012 */
ThrowLoggedException(ExceptionInfo * exception,const ExceptionType severity,const char * reason,const char * description,const char * module,const char * function,const unsigned long line)1013 MagickExport void ThrowLoggedException(ExceptionInfo *exception,
1014 const ExceptionType severity,
1015 const char *reason,
1016 const char *description,
1017 const char *module,
1018 const char *function,
1019 const unsigned long line)
1020 {
1021 const int orig_errno=errno;
1022 MagickBool ignore = MagickFalse;
1023 assert(exception != (ExceptionInfo *) NULL);
1024 assert(function != (const char *) NULL);
1025 assert(exception->signature == MagickSignature);
1026 LockSemaphoreInfo(error_semaphore);
1027 if ((exception->severity > ErrorException) ||
1028 (exception->severity > severity))
1029 {
1030 if (reason)
1031 {
1032 if (description)
1033 (void) LogMagickEvent(severity,module,function,line,"Ignored: %.1024s (%.1024s)",
1034 reason,description);
1035 else
1036 (void) LogMagickEvent(severity,module,function,line,"Ignored: %.1024s",
1037 reason);
1038 }
1039 else
1040 {
1041 (void) LogMagickEvent(severity,module,function,line,
1042 "Ignored: exception contains no reason!");
1043 }
1044 ignore=MagickTrue;
1045 }
1046 if (!ignore)
1047 {
1048 exception->severity=(ExceptionType) severity;
1049
1050 {
1051 char *new_reason = NULL;
1052 if (reason)
1053 new_reason=AcquireString(GetLocaleExceptionMessage(severity,reason));
1054 MagickFreeMemory(exception->reason);
1055 exception->reason=new_reason;
1056 }
1057
1058 {
1059 char *new_description = NULL;
1060 if (description)
1061 new_description=AcquireString(GetLocaleExceptionMessage(severity,description));
1062 MagickFreeMemory(exception->description);
1063 exception->description=new_description;
1064 }
1065
1066 exception->error_number=orig_errno;
1067 {
1068 char *new_module = NULL;
1069 if (module)
1070 new_module=AcquireString(module);
1071 MagickFreeMemory(exception->module);
1072 exception->module=new_module;
1073 }
1074
1075 {
1076 char *new_function = NULL;
1077 if (function)
1078 new_function=AcquireString(function);
1079 MagickFreeMemory(exception->function);
1080 exception->function=new_function;
1081 }
1082
1083 exception->line=line;
1084
1085 if (exception->reason)
1086 {
1087 if (exception->description)
1088 (void) LogMagickEvent(severity,module,function,line,"%.1024s (%.1024s)",
1089 exception->reason,exception->description );
1090 else
1091 (void) LogMagickEvent(severity,module,function,line,"%.1024s",
1092 exception->reason);
1093 }
1094 else
1095 {
1096 (void) LogMagickEvent(severity,module,function,line,
1097 "exception contains no reason!");
1098 }
1099 }
1100 UnlockSemaphoreInfo(error_semaphore);
1101 return;
1102 }
1103