2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % RRRR EEEEE SSSSS OOO U U RRRR CCCC EEEEE %
7 % R R E SS O O U U R R C E %
8 % RRRR EEE SSS O O U U RRRR C EEE %
9 % R R E SS O O U U R R C E %
10 % R R EEEEE SSSSS OOO UUU R R CCCC EEEEE %
13 % Get/Set MagickCore Resources %
20 % Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/cache.h"
44 #include "MagickCore/configure.h"
45 #include "MagickCore/exception.h"
46 #include "MagickCore/exception-private.h"
47 #include "MagickCore/hashmap.h"
48 #include "MagickCore/log.h"
49 #include "MagickCore/image.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/nt-base-private.h"
52 #include "MagickCore/option.h"
53 #include "MagickCore/policy.h"
54 #include "MagickCore/random_.h"
55 #include "MagickCore/registry.h"
56 #include "MagickCore/resource_.h"
57 #include "MagickCore/resource-private.h"
58 #include "MagickCore/semaphore.h"
59 #include "MagickCore/signature-private.h"
60 #include "MagickCore/string_.h"
61 #include "MagickCore/string-private.h"
62 #include "MagickCore/splay-tree.h"
63 #include "MagickCore/thread-private.h"
64 #include "MagickCore/token.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
71 typedef struct _ResourceInfo
102 *random_info = (RandomInfo *) NULL;
107 MagickULLConstant(0), /* initial width */
108 MagickULLConstant(0), /* initial height */
109 MagickULLConstant(0), /* initial area */
110 MagickULLConstant(0), /* initial memory */
111 MagickULLConstant(0), /* initial map */
112 MagickULLConstant(0), /* initial disk */
113 MagickULLConstant(0), /* initial file */
114 MagickULLConstant(0), /* initial thread */
115 MagickULLConstant(0), /* initial throttle */
116 MagickULLConstant(0), /* initial time */
117 MagickULLConstant(10000000), /* width limit */
118 MagickULLConstant(10000000), /* height limit */
119 MagickULLConstant(3072)*1024*1024, /* area limit */
120 MagickULLConstant(1536)*1024*1024, /* memory limit */
121 MagickULLConstant(3072)*1024*1024, /* map limit */
122 MagickResourceInfinity, /* disk limit */
123 MagickULLConstant(768), /* file limit */
124 MagickULLConstant(1), /* thread limit */
125 MagickULLConstant(0), /* throttle limit */
126 MagickResourceInfinity /* time limit */
130 *resource_semaphore = (SemaphoreInfo *) NULL;
133 *temporary_resources = (SplayTreeInfo *) NULL;
136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 % A c q u i r e M a g i c k R e s o u r c e %
144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 % AcquireMagickResource() acquires resources of the specified type.
147 % MagickFalse is returned if the specified resource is exhausted otherwise
150 % The format of the AcquireMagickResource() method is:
152 % MagickBooleanType AcquireMagickResource(const ResourceType type,
153 % const MagickSizeType size)
155 % A description of each parameter follows:
157 % o type: the type of resource.
159 % o size: the number of bytes needed from for this resource.
162 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
163 const MagickSizeType size)
166 resource_current[MaxTextExtent],
167 resource_limit[MaxTextExtent],
168 resource_request[MaxTextExtent];
177 (void) FormatMagickSize(size,MagickFalse,resource_request);
178 if (resource_semaphore == (SemaphoreInfo *) NULL)
179 ActivateSemaphoreInfo(&resource_semaphore);
180 LockSemaphoreInfo(resource_semaphore);
185 resource_info.area=(MagickOffsetType) size;
186 limit=resource_info.area_limit;
187 status=(resource_info.area_limit == MagickResourceInfinity) ||
188 (size < limit) ? MagickTrue : MagickFalse;
189 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
191 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
197 resource_info.memory+=size;
198 limit=resource_info.memory_limit;
199 status=(resource_info.memory_limit == MagickResourceInfinity) ||
200 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
202 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
204 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
210 resource_info.map+=size;
211 limit=resource_info.map_limit;
212 status=(resource_info.map_limit == MagickResourceInfinity) ||
213 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
214 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
216 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
222 resource_info.disk+=size;
223 limit=resource_info.disk_limit;
224 status=(resource_info.disk_limit == MagickResourceInfinity) ||
225 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
227 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
229 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
235 resource_info.file+=size;
236 limit=resource_info.file_limit;
237 status=(resource_info.file_limit == MagickResourceInfinity) ||
238 ((MagickSizeType) resource_info.file < limit) ?
239 MagickTrue : MagickFalse;
240 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
242 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
243 MagickFalse,resource_limit);
248 resource_info.area=(MagickOffsetType) size;
249 limit=resource_info.height_limit;
250 status=(resource_info.area_limit == MagickResourceInfinity) ||
251 (size < limit) ? MagickTrue : MagickFalse;
252 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
254 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,
260 limit=resource_info.thread_limit;
261 status=(resource_info.thread_limit == MagickResourceInfinity) ||
262 ((MagickSizeType) resource_info.thread < limit) ?
263 MagickTrue : MagickFalse;
264 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
266 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
267 MagickFalse,resource_limit);
270 case ThrottleResource:
272 limit=resource_info.throttle_limit;
273 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
274 ((MagickSizeType) resource_info.throttle < limit) ?
275 MagickTrue : MagickFalse;
276 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
277 MagickFalse,resource_current);
278 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
279 MagickFalse,resource_limit);
284 resource_info.time+=size;
285 limit=resource_info.time_limit;
286 status=(resource_info.time_limit == MagickResourceInfinity) ||
287 ((MagickSizeType) resource_info.time < limit) ?
288 MagickTrue : MagickFalse;
289 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
291 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
292 MagickFalse,resource_limit);
297 resource_info.area=(MagickOffsetType) size;
298 limit=resource_info.width_limit;
299 status=(resource_info.area_limit == MagickResourceInfinity) ||
300 (size < limit) ? MagickTrue : MagickFalse;
301 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
303 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
310 UnlockSemaphoreInfo(resource_semaphore);
311 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
312 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
313 resource_request,resource_current,resource_limit);
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 + A s y n c h r o n o u s R e s o u r c e C o m p o n e n t T e r m i n u s %
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 % AsynchronousResourceComponentTerminus() destroys the resource environment.
329 % It differs from ResourceComponentTerminus() in that it can be called from a
330 % asynchronous signal handler.
332 % The format of the ResourceComponentTerminus() method is:
334 % ResourceComponentTerminus(void)
337 MagickPrivate void AsynchronousResourceComponentTerminus(void)
342 if (temporary_resources == (SplayTreeInfo *) NULL)
345 Remove any lingering temporary files.
347 ResetSplayTreeIterator(temporary_resources);
348 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
349 while (path != (const char *) NULL)
351 (void) ShredFile(path);
352 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 % A c q u i r e U n i q u e F i l e R e s o u r c e %
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % AcquireUniqueFileResource() returns a unique file name, and returns a file
368 % descriptor for the file open for reading and writing.
370 % The format of the AcquireUniqueFileResource() method is:
372 % int AcquireUniqueFileResource(char *path)
374 % A description of each parameter follows:
376 % o path: Specifies a pointer to an array of characters. The unique path
377 % name is returned in this array.
381 static void *DestroyTemporaryResources(void *temporary_resource)
383 (void) ShredFile((char *) temporary_resource);
384 temporary_resource=DestroyString((char *) temporary_resource);
385 return((void *) NULL);
388 MagickExport MagickBooleanType GetPathTemplate(char *path)
403 (void) FormatLocaleString(path,MaxTextExtent,"magick-%.20gXXXXXXXXXXXX",
405 exception=AcquireExceptionInfo();
406 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
408 exception=DestroyExceptionInfo(exception);
409 if (directory == (char *) NULL)
410 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
411 if (directory == (char *) NULL)
412 directory=GetEnvironmentValue("MAGICK_TMPDIR");
413 if (directory == (char *) NULL)
414 directory=GetEnvironmentValue("TMPDIR");
415 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
416 if (directory == (char *) NULL)
417 directory=GetEnvironmentValue("TMP");
418 if (directory == (char *) NULL)
419 directory=GetEnvironmentValue("TEMP");
422 if (directory == (char *) NULL)
423 directory=GetEnvironmentValue("MTMPDIR");
425 #if defined(P_tmpdir)
426 if (directory == (char *) NULL)
427 directory=ConstantString(P_tmpdir);
429 if (directory == (char *) NULL)
431 value=GetPolicyValue("temporary-path");
432 if (value != (char *) NULL)
433 (void) CloneString(&directory,value);
434 if (strlen(directory) > (MaxTextExtent-25))
436 directory=DestroyString(directory);
439 status=GetPathAttributes(directory,&attributes);
440 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
442 directory=DestroyString(directory);
445 if (directory[strlen(directory)-1] == *DirectorySeparator)
446 (void) FormatLocaleString(path,MaxTextExtent,"%smagick-%.20gXXXXXXXXXXXX",
447 directory,(double) getpid());
449 (void) FormatLocaleString(path,MaxTextExtent,
450 "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,
452 directory=DestroyString(directory);
453 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
459 Ghostscript does not like backslashes so we need to replace them. The
460 forward slash also works under Windows.
462 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
463 if (*p == *DirectorySeparator)
470 MagickExport int AcquireUniqueFileResource(char *path)
472 #if !defined(O_NOFOLLOW)
475 #if !defined(TMP_MAX)
476 # define TMP_MAX 238328
490 portable_filename[65] =
491 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
499 assert(path != (char *) NULL);
500 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
501 if (random_info == (RandomInfo *) NULL)
502 random_info=AcquireRandomInfo();
504 for (i=0; i < (ssize_t) TMP_MAX; i++)
507 Get temporary pathname.
509 (void) GetPathTemplate(path);
510 key=GetRandomKey(random_info,6);
511 p=path+strlen(path)-12;
512 datum=GetStringInfoDatum(key);
513 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
515 c=(int) (datum[i] & 0x3f);
516 *p++=portable_filename[c];
518 key=DestroyStringInfo(key);
519 #if defined(MAGICKCORE_HAVE_MKSTEMP)
522 setmode(file,O_BINARY);
527 key=GetRandomKey(random_info,12);
528 p=path+strlen(path)-12;
529 datum=GetStringInfoDatum(key);
530 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
532 c=(int) (datum[i] & 0x3f);
533 *p++=portable_filename[c];
535 key=DestroyStringInfo(key);
536 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
538 if ((file >= 0) || (errno != EEXIST))
541 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
544 if (resource_semaphore == (SemaphoreInfo *) NULL)
545 ActivateSemaphoreInfo(&resource_semaphore);
546 LockSemaphoreInfo(resource_semaphore);
547 if (temporary_resources == (SplayTreeInfo *) NULL)
548 temporary_resources=NewSplayTree(CompareSplayTreeString,
549 DestroyTemporaryResources,(void *(*)(void *)) NULL);
550 UnlockSemaphoreInfo(resource_semaphore);
551 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
552 (const void *) NULL);
557 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 % G e t M a g i c k R e s o u r c e %
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
567 % GetMagickResource() returns the specified resource.
569 % The format of the GetMagickResource() method is:
571 % MagickSizeType GetMagickResource(const ResourceType type)
573 % A description of each parameter follows:
575 % o type: the type of resource.
578 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
584 LockSemaphoreInfo(resource_semaphore);
589 resource=(MagickSizeType) resource_info.width;
594 resource=(MagickSizeType) resource_info.height;
599 resource=(MagickSizeType) resource_info.area;
604 resource=(MagickSizeType) resource_info.memory;
609 resource=(MagickSizeType) resource_info.map;
614 resource=(MagickSizeType) resource_info.disk;
619 resource=(MagickSizeType) resource_info.file;
624 resource=(MagickSizeType) resource_info.thread;
627 case ThrottleResource:
629 resource=(MagickSizeType) resource_info.throttle;
634 resource=(MagickSizeType) resource_info.time;
640 UnlockSemaphoreInfo(resource_semaphore);
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % G e t M a g i c k R e s o u r c e L i m i t %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655 % GetMagickResourceLimit() returns the specified resource limit.
657 % The format of the GetMagickResourceLimit() method is:
659 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
661 % A description of each parameter follows:
663 % o type: the type of resource.
666 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
672 if (resource_semaphore == (SemaphoreInfo *) NULL)
673 ActivateSemaphoreInfo(&resource_semaphore);
674 LockSemaphoreInfo(resource_semaphore);
679 resource=resource_info.width_limit;
684 resource=resource_info.height_limit;
689 resource=resource_info.area_limit;
694 resource=resource_info.memory_limit;
699 resource=resource_info.map_limit;
704 resource=resource_info.disk_limit;
709 resource=resource_info.file_limit;
714 resource=resource_info.thread_limit;
717 case ThrottleResource:
719 resource=resource_info.throttle_limit;
724 resource=resource_info.time_limit;
730 UnlockSemaphoreInfo(resource_semaphore);
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
739 % L i s t M a g i c k R e s o u r c e I n f o %
743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745 % ListMagickResourceInfo() lists the resource info to a file.
747 % The format of the ListMagickResourceInfo method is:
749 % MagickBooleanType ListMagickResourceInfo(FILE *file,
750 % ExceptionInfo *exception)
752 % A description of each parameter follows.
754 % o file: An pointer to a FILE.
756 % o exception: return any errors or warnings in this structure.
759 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
760 ExceptionInfo *magick_unused(exception))
763 area_limit[MaxTextExtent],
764 disk_limit[MaxTextExtent],
765 height_limit[MaxTextExtent],
766 map_limit[MaxTextExtent],
767 memory_limit[MaxTextExtent],
768 time_limit[MaxTextExtent],
769 width_limit[MaxTextExtent];
771 if (file == (const FILE *) NULL)
773 if (resource_semaphore == (SemaphoreInfo *) NULL)
774 ActivateSemaphoreInfo(&resource_semaphore);
775 LockSemaphoreInfo(resource_semaphore);
776 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,width_limit);
777 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,height_limit);
778 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,area_limit);
779 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,memory_limit);
780 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,map_limit);
781 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
782 if (resource_info.disk_limit != MagickResourceInfinity)
783 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,disk_limit);
784 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
785 if (resource_info.time_limit != MagickResourceInfinity)
786 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
787 ((MagickOffsetType) resource_info.time_limit));
788 (void) FormatLocaleFile(file,"Resource limits:\n");
789 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
790 (void) FormatLocaleFile(file," Height: %s\n",heigth_limit);
791 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
792 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
793 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
794 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
795 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
796 resource_info.file_limit));
797 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
798 resource_info.thread_limit));
799 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
800 ((MagickOffsetType) resource_info.throttle_limit));
801 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
803 UnlockSemaphoreInfo(resource_semaphore);
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812 % R e l i n q u i s h M a g i c k R e s o u r c e %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
818 % RelinquishMagickResource() relinquishes resources of the specified type.
820 % The format of the RelinquishMagickResource() method is:
822 % void RelinquishMagickResource(const ResourceType type,
823 % const MagickSizeType size)
825 % A description of each parameter follows:
827 % o type: the type of resource.
829 % o size: the size of the resource.
832 MagickExport void RelinquishMagickResource(const ResourceType type,
833 const MagickSizeType size)
836 resource_current[MaxTextExtent],
837 resource_limit[MaxTextExtent],
838 resource_request[MaxTextExtent];
840 (void) FormatMagickSize(size,MagickFalse,resource_request);
841 if (resource_semaphore == (SemaphoreInfo *) NULL)
842 ActivateSemaphoreInfo(&resource_semaphore);
843 LockSemaphoreInfo(resource_semaphore);
848 resource_info.width=(MagickOffsetType) size;
849 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
851 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
857 resource_info.width=(MagickOffsetType) size;
858 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
860 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
866 resource_info.area=(MagickOffsetType) size;
867 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
869 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
875 resource_info.memory-=size;
876 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
877 MagickTrue,resource_current);
878 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
884 resource_info.map-=size;
885 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
887 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
893 resource_info.disk-=size;
894 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
896 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
902 resource_info.file-=size;
903 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
905 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
906 MagickFalse,resource_limit);
911 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
913 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
914 MagickFalse,resource_limit);
917 case ThrottleResource:
919 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
920 MagickFalse,resource_current);
921 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
922 MagickFalse,resource_limit);
927 resource_info.time-=size;
928 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
930 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
931 MagickFalse,resource_limit);
937 UnlockSemaphoreInfo(resource_semaphore);
938 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
939 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
940 resource_request,resource_current,resource_limit);
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948 % R e l i n q u i s h U n i q u e F i l e R e s o u r c e %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 % RelinquishUniqueFileResource() relinquishes a unique file resource.
956 % The format of the RelinquishUniqueFileResource() method is:
958 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
960 % A description of each parameter follows:
962 % o name: the name of the temporary resource.
965 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
968 cache_path[MaxTextExtent];
970 assert(path != (const char *) NULL);
971 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
972 if (resource_semaphore == (SemaphoreInfo *) NULL)
973 ActivateSemaphoreInfo(&resource_semaphore);
974 LockSemaphoreInfo(resource_semaphore);
975 if (temporary_resources != (SplayTreeInfo *) NULL)
976 (void) DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
977 UnlockSemaphoreInfo(resource_semaphore);
978 (void) CopyMagickString(cache_path,path,MaxTextExtent);
979 AppendImageFormat("cache",cache_path);
980 (void) ShredFile(cache_path);
981 return(ShredFile(path));
985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989 + R e s o u r c e C o m p o n e n t G e n e s i s %
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 % ResourceComponentGenesis() instantiates the resource component.
997 % The format of the ResourceComponentGenesis method is:
999 % MagickBooleanType ResourceComponentGenesis(void)
1003 static inline size_t MagickMax(const size_t x,const size_t y)
1010 static inline MagickSizeType StringToSizeType(const char *string,
1011 const double interval)
1016 value=SiPrefixToDoubleInterval(string,interval);
1017 if (value >= (double) MagickULLConstant(~0))
1018 return(MagickULLConstant(~0));
1019 return((MagickSizeType) value);
1022 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1036 Set Magick resource limits.
1038 if (resource_semaphore == (SemaphoreInfo *) NULL)
1039 resource_semaphore=AcquireSemaphoreInfo();
1040 pagesize=GetMagickPageSize();
1042 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1043 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1045 memory=(MagickSizeType) pages*pagesize;
1046 if ((pagesize <= 0) || (pages <= 0))
1047 memory=2048UL*1024UL*1024UL;
1048 #if defined(PixelCacheThreshold)
1049 memory=PixelCacheThreshold;
1051 (void) SetMagickResourceLimit(AreaResource,2*memory);
1052 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1053 if (limit != (char *) NULL)
1055 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1057 limit=DestroyString(limit);
1059 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1060 if (limit != (char *) NULL)
1062 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1064 limit=DestroyString(limit);
1066 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1067 if (limit != (char *) NULL)
1069 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1070 limit=DestroyString(limit);
1072 (void) SetMagickResourceLimit(MemoryResource,memory);
1073 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1074 if (limit != (char *) NULL)
1076 (void) SetMagickResourceLimit(MemoryResource,
1077 StringToSizeType(limit,100.0));
1078 limit=DestroyString(limit);
1080 (void) SetMagickResourceLimit(MapResource,2*memory);
1081 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1082 if (limit != (char *) NULL)
1084 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1085 limit=DestroyString(limit);
1087 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1088 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1089 if (limit != (char *) NULL)
1091 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1092 limit=DestroyString(limit);
1095 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1096 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1098 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1104 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1105 files=(ssize_t) resources.rlim_cur;
1108 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1110 files=(ssize_t) getdtablesize();
1114 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1116 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1117 if (limit != (char *) NULL)
1119 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1121 limit=DestroyString(limit);
1123 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1124 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1125 if (limit != (char *) NULL)
1127 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1129 limit=DestroyString(limit);
1131 (void) SetMagickResourceLimit(ThrottleResource,0);
1132 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1133 if (limit != (char *) NULL)
1135 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1137 limit=DestroyString(limit);
1139 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1140 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1141 if (limit != (char *) NULL)
1143 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1144 limit=DestroyString(limit);
1150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1154 + R e s o u r c e C o m p o n e n t T e r m i n u s %
1158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1160 % ResourceComponentTerminus() destroys the resource component.
1162 % The format of the ResourceComponentTerminus() method is:
1164 % ResourceComponentTerminus(void)
1167 MagickPrivate void ResourceComponentTerminus(void)
1169 if (resource_semaphore == (SemaphoreInfo *) NULL)
1170 resource_semaphore=AcquireSemaphoreInfo();
1171 LockSemaphoreInfo(resource_semaphore);
1172 if (temporary_resources != (SplayTreeInfo *) NULL)
1173 temporary_resources=DestroySplayTree(temporary_resources);
1174 if (random_info != (RandomInfo *) NULL)
1175 random_info=DestroyRandomInfo(random_info);
1176 UnlockSemaphoreInfo(resource_semaphore);
1177 RelinquishSemaphoreInfo(&resource_semaphore);
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % S e t M a g i c k R e s o u r c e L i m i t %
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1191 % SetMagickResourceLimit() sets the limit for a particular resource.
1193 % The format of the SetMagickResourceLimit() method is:
1195 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1196 % const MagickSizeType limit)
1198 % A description of each parameter follows:
1200 % o type: the type of resource.
1202 % o limit: the maximum limit for the resource.
1206 static inline MagickSizeType MagickMin(const MagickSizeType x,
1207 const MagickSizeType y)
1214 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1215 const MagickSizeType limit)
1220 if (resource_semaphore == (SemaphoreInfo *) NULL)
1221 resource_semaphore=AcquireSemaphoreInfo();
1222 LockSemaphoreInfo(resource_semaphore);
1223 value=(char *) NULL;
1228 resource_info.width_limit=limit;
1229 value=GetPolicyValue("width");
1230 if (value != (char *) NULL)
1231 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1235 case HeightResource:
1237 resource_info.height_limit=limit;
1238 value=GetPolicyValue("height");
1239 if (value != (char *) NULL)
1240 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1246 resource_info.area_limit=limit;
1247 value=GetPolicyValue("area");
1248 if (value != (char *) NULL)
1249 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1252 case MemoryResource:
1254 resource_info.memory_limit=limit;
1255 value=GetPolicyValue("memory");
1256 if (value != (char *) NULL)
1257 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1263 resource_info.map_limit=limit;
1264 value=GetPolicyValue("map");
1265 if (value != (char *) NULL)
1266 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1271 resource_info.disk_limit=limit;
1272 value=GetPolicyValue("disk");
1273 if (value != (char *) NULL)
1274 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1279 resource_info.file_limit=limit;
1280 value=GetPolicyValue("file");
1281 if (value != (char *) NULL)
1282 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1285 case ThreadResource:
1287 resource_info.thread_limit=limit;
1288 value=GetPolicyValue("thread");
1289 if (value != (char *) NULL)
1290 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1292 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1293 resource_info.thread_limit=GetOpenMPMaximumThreads();
1294 else if (resource_info.thread_limit == 0)
1295 resource_info.thread_limit=1;
1298 case ThrottleResource:
1300 resource_info.throttle_limit=limit;
1301 value=GetPolicyValue("throttle");
1302 if (value != (char *) NULL)
1303 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1305 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1306 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1311 resource_info.time_limit=limit;
1312 value=GetPolicyValue("time");
1313 if (value != (char *) NULL)
1314 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1320 if (value != (char *) NULL)
1321 value=DestroyString(value);
1322 UnlockSemaphoreInfo(resource_semaphore);