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,"B",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,
190 "B",resource_current);
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,
203 "B",resource_current);
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,
215 "B",resource_current);
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,
228 "B",resource_current);
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,
241 "B",resource_current);
242 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
243 MagickFalse,"B",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,
253 "P",resource_current);
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,
265 "B",resource_current);
266 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
267 MagickFalse,"B",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,"B",resource_current);
278 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
279 MagickFalse,"B",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,
290 "B",resource_current);
291 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
292 MagickFalse,"B",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,
302 "P",resource_current);
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,"P",
778 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
780 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",area_limit);
781 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
783 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",map_limit);
784 (void) CopyMagickString(disk_limit,"unlimited",MaxTextExtent);
785 if (resource_info.disk_limit != MagickResourceInfinity)
786 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",disk_limit);
787 (void) CopyMagickString(time_limit,"unlimited",MaxTextExtent);
788 if (resource_info.time_limit != MagickResourceInfinity)
789 (void) FormatLocaleString(time_limit,MaxTextExtent,"%.20g",(double)
790 ((MagickOffsetType) resource_info.time_limit));
791 (void) FormatLocaleFile(file,"Resource limits:\n");
792 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
793 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
794 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
795 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
796 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
797 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
798 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
799 resource_info.file_limit));
800 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
801 resource_info.thread_limit));
802 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
803 ((MagickOffsetType) resource_info.throttle_limit));
804 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
806 UnlockSemaphoreInfo(resource_semaphore);
811 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 % R e l i n q u i s h M a g i c k R e s o u r c e %
819 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
821 % RelinquishMagickResource() relinquishes resources of the specified type.
823 % The format of the RelinquishMagickResource() method is:
825 % void RelinquishMagickResource(const ResourceType type,
826 % const MagickSizeType size)
828 % A description of each parameter follows:
830 % o type: the type of resource.
832 % o size: the size of the resource.
835 MagickExport void RelinquishMagickResource(const ResourceType type,
836 const MagickSizeType size)
839 resource_current[MaxTextExtent],
840 resource_limit[MaxTextExtent],
841 resource_request[MaxTextExtent];
843 (void) FormatMagickSize(size,MagickFalse,"B",resource_request);
844 if (resource_semaphore == (SemaphoreInfo *) NULL)
845 ActivateSemaphoreInfo(&resource_semaphore);
846 LockSemaphoreInfo(resource_semaphore);
851 resource_info.width=(MagickOffsetType) size;
852 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
853 "P",resource_current);
854 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
860 resource_info.width=(MagickOffsetType) size;
861 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
862 "P",resource_current);
863 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,
869 resource_info.area=(MagickOffsetType) size;
870 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
871 "B",resource_current);
872 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
878 resource_info.memory-=size;
879 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
880 MagickTrue,"B",resource_current);
881 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,
887 resource_info.map-=size;
888 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
889 "B",resource_current);
890 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,
896 resource_info.disk-=size;
897 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
898 "B",resource_current);
899 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,
905 resource_info.file-=size;
906 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
907 "B",resource_current);
908 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
909 MagickFalse,"B",resource_limit);
914 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
915 "B",resource_current);
916 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
917 MagickFalse,"B",resource_limit);
920 case ThrottleResource:
922 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
923 MagickFalse,"B",resource_current);
924 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
925 MagickFalse,"B",resource_limit);
930 resource_info.time-=size;
931 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
932 "B",resource_current);
933 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
934 MagickFalse,"B",resource_limit);
940 UnlockSemaphoreInfo(resource_semaphore);
941 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
942 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
943 resource_request,resource_current,resource_limit);
947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
951 % 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 %
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957 % RelinquishUniqueFileResource() relinquishes a unique file resource.
959 % The format of the RelinquishUniqueFileResource() method is:
961 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
963 % A description of each parameter follows:
965 % o name: the name of the temporary resource.
968 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
971 cache_path[MaxTextExtent];
973 assert(path != (const char *) NULL);
974 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
975 if (resource_semaphore == (SemaphoreInfo *) NULL)
976 ActivateSemaphoreInfo(&resource_semaphore);
977 LockSemaphoreInfo(resource_semaphore);
978 if (temporary_resources != (SplayTreeInfo *) NULL)
979 (void) DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
980 UnlockSemaphoreInfo(resource_semaphore);
981 (void) CopyMagickString(cache_path,path,MaxTextExtent);
982 AppendImageFormat("cache",cache_path);
983 (void) ShredFile(cache_path);
984 return(ShredFile(path));
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 + R e s o u r c e C o m p o n e n t G e n e s i s %
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998 % ResourceComponentGenesis() instantiates the resource component.
1000 % The format of the ResourceComponentGenesis method is:
1002 % MagickBooleanType ResourceComponentGenesis(void)
1006 static inline size_t MagickMax(const size_t x,const size_t y)
1013 static inline MagickSizeType StringToSizeType(const char *string,
1014 const double interval)
1019 value=SiPrefixToDoubleInterval(string,interval);
1020 if (value >= (double) MagickULLConstant(~0))
1021 return(MagickULLConstant(~0));
1022 return((MagickSizeType) value);
1025 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1039 Set Magick resource limits.
1041 if (resource_semaphore == (SemaphoreInfo *) NULL)
1042 resource_semaphore=AcquireSemaphoreInfo();
1043 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1044 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1045 if (limit != (char *) NULL)
1047 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1049 limit=DestroyString(limit);
1051 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1052 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1053 if (limit != (char *) NULL)
1055 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1057 limit=DestroyString(limit);
1059 pagesize=GetMagickPageSize();
1061 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1062 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1064 memory=(MagickSizeType) pages*pagesize;
1065 if ((pagesize <= 0) || (pages <= 0))
1066 memory=2048UL*1024UL*1024UL;
1067 #if defined(PixelCacheThreshold)
1068 memory=PixelCacheThreshold;
1070 (void) SetMagickResourceLimit(AreaResource,2*memory);
1071 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1072 if (limit != (char *) NULL)
1074 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1075 limit=DestroyString(limit);
1077 (void) SetMagickResourceLimit(MemoryResource,memory);
1078 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1079 if (limit != (char *) NULL)
1081 (void) SetMagickResourceLimit(MemoryResource,
1082 StringToSizeType(limit,100.0));
1083 limit=DestroyString(limit);
1085 (void) SetMagickResourceLimit(MapResource,2*memory);
1086 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1087 if (limit != (char *) NULL)
1089 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1090 limit=DestroyString(limit);
1092 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1093 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1094 if (limit != (char *) NULL)
1096 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1097 limit=DestroyString(limit);
1100 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1101 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1103 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1109 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1110 files=(ssize_t) resources.rlim_cur;
1113 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1115 files=(ssize_t) getdtablesize();
1119 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1121 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1122 if (limit != (char *) NULL)
1124 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1126 limit=DestroyString(limit);
1128 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1129 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1130 if (limit != (char *) NULL)
1132 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1134 limit=DestroyString(limit);
1136 (void) SetMagickResourceLimit(ThrottleResource,0);
1137 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1138 if (limit != (char *) NULL)
1140 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1142 limit=DestroyString(limit);
1144 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1145 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1146 if (limit != (char *) NULL)
1148 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1149 limit=DestroyString(limit);
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1159 + 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 %
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165 % ResourceComponentTerminus() destroys the resource component.
1167 % The format of the ResourceComponentTerminus() method is:
1169 % ResourceComponentTerminus(void)
1172 MagickPrivate void ResourceComponentTerminus(void)
1174 if (resource_semaphore == (SemaphoreInfo *) NULL)
1175 resource_semaphore=AcquireSemaphoreInfo();
1176 LockSemaphoreInfo(resource_semaphore);
1177 if (temporary_resources != (SplayTreeInfo *) NULL)
1178 temporary_resources=DestroySplayTree(temporary_resources);
1179 if (random_info != (RandomInfo *) NULL)
1180 random_info=DestroyRandomInfo(random_info);
1181 UnlockSemaphoreInfo(resource_semaphore);
1182 RelinquishSemaphoreInfo(&resource_semaphore);
1186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1190 % S e t M a g i c k R e s o u r c e L i m i t %
1194 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1196 % SetMagickResourceLimit() sets the limit for a particular resource.
1198 % The format of the SetMagickResourceLimit() method is:
1200 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1201 % const MagickSizeType limit)
1203 % A description of each parameter follows:
1205 % o type: the type of resource.
1207 % o limit: the maximum limit for the resource.
1211 static inline MagickSizeType MagickMin(const MagickSizeType x,
1212 const MagickSizeType y)
1219 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1220 const MagickSizeType limit)
1225 if (resource_semaphore == (SemaphoreInfo *) NULL)
1226 resource_semaphore=AcquireSemaphoreInfo();
1227 LockSemaphoreInfo(resource_semaphore);
1228 value=(char *) NULL;
1233 resource_info.width_limit=limit;
1234 value=GetPolicyValue("width");
1235 if (value != (char *) NULL)
1236 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1240 case HeightResource:
1242 resource_info.height_limit=limit;
1243 value=GetPolicyValue("height");
1244 if (value != (char *) NULL)
1245 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1251 resource_info.area_limit=limit;
1252 value=GetPolicyValue("area");
1253 if (value != (char *) NULL)
1254 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1257 case MemoryResource:
1259 resource_info.memory_limit=limit;
1260 value=GetPolicyValue("memory");
1261 if (value != (char *) NULL)
1262 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1268 resource_info.map_limit=limit;
1269 value=GetPolicyValue("map");
1270 if (value != (char *) NULL)
1271 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1276 resource_info.disk_limit=limit;
1277 value=GetPolicyValue("disk");
1278 if (value != (char *) NULL)
1279 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1284 resource_info.file_limit=limit;
1285 value=GetPolicyValue("file");
1286 if (value != (char *) NULL)
1287 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1290 case ThreadResource:
1292 resource_info.thread_limit=limit;
1293 value=GetPolicyValue("thread");
1294 if (value != (char *) NULL)
1295 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1297 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1298 resource_info.thread_limit=GetOpenMPMaximumThreads();
1299 else if (resource_info.thread_limit == 0)
1300 resource_info.thread_limit=1;
1303 case ThrottleResource:
1305 resource_info.throttle_limit=limit;
1306 value=GetPolicyValue("throttle");
1307 if (value != (char *) NULL)
1308 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1310 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1311 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1316 resource_info.time_limit=limit;
1317 value=GetPolicyValue("time");
1318 if (value != (char *) NULL)
1319 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1325 if (value != (char *) NULL)
1326 value=DestroyString(value);
1327 UnlockSemaphoreInfo(resource_semaphore);