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/image-private.h"
51 #include "MagickCore/memory_.h"
52 #include "MagickCore/nt-base-private.h"
53 #include "MagickCore/option.h"
54 #include "MagickCore/policy.h"
55 #include "MagickCore/random_.h"
56 #include "MagickCore/registry.h"
57 #include "MagickCore/resource_.h"
58 #include "MagickCore/resource-private.h"
59 #include "MagickCore/semaphore.h"
60 #include "MagickCore/signature-private.h"
61 #include "MagickCore/string_.h"
62 #include "MagickCore/string-private.h"
63 #include "MagickCore/splay-tree.h"
64 #include "MagickCore/thread-private.h"
65 #include "MagickCore/token.h"
66 #include "MagickCore/utility.h"
67 #include "MagickCore/utility-private.h"
72 typedef struct _ResourceInfo
103 *random_info = (RandomInfo *) NULL;
108 MagickULLConstant(0), /* initial width */
109 MagickULLConstant(0), /* initial height */
110 MagickULLConstant(0), /* initial area */
111 MagickULLConstant(0), /* initial memory */
112 MagickULLConstant(0), /* initial map */
113 MagickULLConstant(0), /* initial disk */
114 MagickULLConstant(0), /* initial file */
115 MagickULLConstant(0), /* initial thread */
116 MagickULLConstant(0), /* initial throttle */
117 MagickULLConstant(0), /* initial time */
118 (INT_MAX/(5*sizeof(Quantum))), /* width limit */
119 (INT_MAX/(5*sizeof(Quantum))), /* height limit */
120 MagickULLConstant(3072)*1024*1024, /* area limit */
121 MagickULLConstant(1536)*1024*1024, /* memory limit */
122 MagickULLConstant(3072)*1024*1024, /* map limit */
123 MagickResourceInfinity, /* disk limit */
124 MagickULLConstant(768), /* file limit */
125 MagickULLConstant(1), /* thread limit */
126 MagickULLConstant(0), /* throttle limit */
127 MagickResourceInfinity /* time limit */
131 *resource_semaphore = (SemaphoreInfo *) NULL;
134 *temporary_resources = (SplayTreeInfo *) NULL;
137 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % A c q u i r e M a g i c k R e s o u r c e %
145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 % AcquireMagickResource() acquires resources of the specified type.
148 % MagickFalse is returned if the specified resource is exhausted otherwise
151 % The format of the AcquireMagickResource() method is:
153 % MagickBooleanType AcquireMagickResource(const ResourceType type,
154 % const MagickSizeType size)
156 % A description of each parameter follows:
158 % o type: the type of resource.
160 % o size: the number of bytes needed from for this resource.
163 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
164 const MagickSizeType size)
167 resource_current[MagickFormatExtent],
168 resource_limit[MagickFormatExtent],
169 resource_request[MagickFormatExtent];
178 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
180 if (resource_semaphore == (SemaphoreInfo *) NULL)
181 ActivateSemaphoreInfo(&resource_semaphore);
182 LockSemaphoreInfo(resource_semaphore);
187 resource_info.area=(MagickOffsetType) size;
188 limit=resource_info.area_limit;
189 status=(resource_info.area_limit == MagickResourceInfinity) ||
190 (size < limit) ? MagickTrue : MagickFalse;
191 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
192 "B",MagickFormatExtent,resource_current);
193 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
194 MagickFormatExtent,resource_limit);
199 resource_info.memory+=size;
200 limit=resource_info.memory_limit;
201 status=(resource_info.memory_limit == MagickResourceInfinity) ||
202 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
204 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
205 "B",MagickFormatExtent,resource_current);
206 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
207 MagickFormatExtent,resource_limit);
212 resource_info.map+=size;
213 limit=resource_info.map_limit;
214 status=(resource_info.map_limit == MagickResourceInfinity) ||
215 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
216 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
217 "B",MagickFormatExtent,resource_current);
218 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
219 MagickFormatExtent,resource_limit);
224 resource_info.disk+=size;
225 limit=resource_info.disk_limit;
226 status=(resource_info.disk_limit == MagickResourceInfinity) ||
227 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
229 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
230 "B",MagickFormatExtent,resource_current);
231 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
232 MagickFormatExtent,resource_limit);
237 resource_info.file+=size;
238 limit=resource_info.file_limit;
239 status=(resource_info.file_limit == MagickResourceInfinity) ||
240 ((MagickSizeType) resource_info.file < limit) ?
241 MagickTrue : MagickFalse;
242 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
243 "B",MagickFormatExtent,resource_current);
244 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
245 MagickFalse,"B",MagickFormatExtent,resource_limit);
250 resource_info.area=(MagickOffsetType) size;
251 limit=resource_info.height_limit;
252 status=(resource_info.area_limit == MagickResourceInfinity) ||
253 (size < limit) ? MagickTrue : MagickFalse;
254 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
255 "P",MagickFormatExtent,resource_current);
256 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
257 MagickFormatExtent,resource_limit);
262 limit=resource_info.thread_limit;
263 status=(resource_info.thread_limit == MagickResourceInfinity) ||
264 ((MagickSizeType) resource_info.thread < limit) ?
265 MagickTrue : MagickFalse;
266 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
267 "B",MagickFormatExtent,resource_current);
268 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
269 MagickFalse,"B",MagickFormatExtent,resource_limit);
272 case ThrottleResource:
274 limit=resource_info.throttle_limit;
275 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
276 ((MagickSizeType) resource_info.throttle < limit) ?
277 MagickTrue : MagickFalse;
278 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
279 MagickFalse,"B",MagickFormatExtent,resource_current);
280 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
281 MagickFalse,"B",MagickFormatExtent,resource_limit);
286 resource_info.time+=size;
287 limit=resource_info.time_limit;
288 status=(resource_info.time_limit == MagickResourceInfinity) ||
289 ((MagickSizeType) resource_info.time < limit) ?
290 MagickTrue : MagickFalse;
291 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
292 "B",MagickFormatExtent,resource_current);
293 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
294 MagickFalse,"B",MagickFormatExtent,resource_limit);
299 resource_info.area=(MagickOffsetType) size;
300 limit=resource_info.width_limit;
301 status=(resource_info.area_limit == MagickResourceInfinity) ||
302 (size < limit) ? MagickTrue : MagickFalse;
303 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
304 "P",MagickFormatExtent,resource_current);
305 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
306 MagickFormatExtent,resource_limit);
312 UnlockSemaphoreInfo(resource_semaphore);
313 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
314 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
315 resource_request,resource_current,resource_limit);
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 + 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 %
328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 % AsynchronousResourceComponentTerminus() destroys the resource environment.
331 % It differs from ResourceComponentTerminus() in that it can be called from a
332 % asynchronous signal handler.
334 % The format of the ResourceComponentTerminus() method is:
336 % ResourceComponentTerminus(void)
339 MagickPrivate void AsynchronousResourceComponentTerminus(void)
344 if (temporary_resources == (SplayTreeInfo *) NULL)
347 Remove any lingering temporary files.
349 ResetSplayTreeIterator(temporary_resources);
350 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
351 while (path != (const char *) NULL)
353 (void) ShredFile(path);
354 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
359 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
363 % 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 %
367 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % AcquireUniqueFileResource() returns a unique file name, and returns a file
370 % descriptor for the file open for reading and writing.
372 % The format of the AcquireUniqueFileResource() method is:
374 % int AcquireUniqueFileResource(char *path)
376 % A description of each parameter follows:
378 % o path: Specifies a pointer to an array of characters. The unique path
379 % name is returned in this array.
383 static void *DestroyTemporaryResources(void *temporary_resource)
385 (void) ShredFile((char *) temporary_resource);
386 temporary_resource=DestroyString((char *) temporary_resource);
387 return((void *) NULL);
390 MagickExport MagickBooleanType GetPathTemplate(char *path)
405 (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20gXXXXXXXXXXXX",
407 exception=AcquireExceptionInfo();
408 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
410 exception=DestroyExceptionInfo(exception);
411 if (directory == (char *) NULL)
412 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
413 if (directory == (char *) NULL)
414 directory=GetEnvironmentValue("MAGICK_TMPDIR");
415 if (directory == (char *) NULL)
416 directory=GetEnvironmentValue("TMPDIR");
417 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__)
418 if (directory == (char *) NULL)
419 directory=GetEnvironmentValue("TMP");
420 if (directory == (char *) NULL)
421 directory=GetEnvironmentValue("TEMP");
424 if (directory == (char *) NULL)
425 directory=GetEnvironmentValue("MTMPDIR");
427 #if defined(P_tmpdir)
428 if (directory == (char *) NULL)
429 directory=ConstantString(P_tmpdir);
431 if (directory == (char *) NULL)
433 value=GetPolicyValue("temporary-path");
434 if (value != (char *) NULL)
435 (void) CloneString(&directory,value);
436 if (strlen(directory) > (MagickPathExtent-25))
438 directory=DestroyString(directory);
441 status=GetPathAttributes(directory,&attributes);
442 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
444 directory=DestroyString(directory);
447 if (directory[strlen(directory)-1] == *DirectorySeparator)
448 (void) FormatLocaleString(path,MagickPathExtent,
449 "%smagick-%.20gXXXXXXXXXXXX",directory,(double) getpid());
451 (void) FormatLocaleString(path,MagickPathExtent,
452 "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,(double)
454 directory=DestroyString(directory);
455 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
461 Ghostscript does not like backslashes so we need to replace them. The
462 forward slash also works under Windows.
464 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
465 if (*p == *DirectorySeparator)
472 MagickExport int AcquireUniqueFileResource(char *path)
474 #if !defined(O_NOFOLLOW)
477 #if !defined(TMP_MAX)
478 # define TMP_MAX 238328
492 portable_filename[65] =
493 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
501 assert(path != (char *) NULL);
502 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
503 if (random_info == (RandomInfo *) NULL)
505 LockSemaphoreInfo(resource_semaphore);
506 if (random_info == (RandomInfo *) NULL)
507 random_info=AcquireRandomInfo();
508 UnlockSemaphoreInfo(resource_semaphore);
511 for (i=0; i < (ssize_t) TMP_MAX; i++)
514 Get temporary pathname.
516 (void) GetPathTemplate(path);
517 key=GetRandomKey(random_info,6);
518 p=path+strlen(path)-12;
519 datum=GetStringInfoDatum(key);
520 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
522 c=(int) (datum[i] & 0x3f);
523 *p++=portable_filename[c];
525 key=DestroyStringInfo(key);
526 #if defined(MAGICKCORE_HAVE_MKSTEMP)
530 (void) fchmod(file,0600);
532 setmode(file,O_BINARY);
537 key=GetRandomKey(random_info,12);
538 p=path+strlen(path)-12;
539 datum=GetStringInfoDatum(key);
540 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
542 c=(int) (datum[i] & 0x3f);
543 *p++=portable_filename[c];
545 key=DestroyStringInfo(key);
546 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
548 if ((file >= 0) || (errno != EEXIST))
551 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
554 if (resource_semaphore == (SemaphoreInfo *) NULL)
555 ActivateSemaphoreInfo(&resource_semaphore);
556 LockSemaphoreInfo(resource_semaphore);
557 if (temporary_resources == (SplayTreeInfo *) NULL)
558 temporary_resources=NewSplayTree(CompareSplayTreeString,
559 DestroyTemporaryResources,(void *(*)(void *)) NULL);
560 UnlockSemaphoreInfo(resource_semaphore);
561 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
562 (const void *) NULL);
567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 % G e t M a g i c k R e s o u r c e %
575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 % GetMagickResource() returns the specified resource.
579 % The format of the GetMagickResource() method is:
581 % MagickSizeType GetMagickResource(const ResourceType type)
583 % A description of each parameter follows:
585 % o type: the type of resource.
588 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
594 LockSemaphoreInfo(resource_semaphore);
599 resource=(MagickSizeType) resource_info.width;
604 resource=(MagickSizeType) resource_info.height;
609 resource=(MagickSizeType) resource_info.area;
614 resource=(MagickSizeType) resource_info.memory;
619 resource=(MagickSizeType) resource_info.map;
624 resource=(MagickSizeType) resource_info.disk;
629 resource=(MagickSizeType) resource_info.file;
634 resource=(MagickSizeType) resource_info.thread;
637 case ThrottleResource:
639 resource=(MagickSizeType) resource_info.throttle;
644 resource=(MagickSizeType) resource_info.time;
650 UnlockSemaphoreInfo(resource_semaphore);
655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 % G e t M a g i c k R e s o u r c e L i m i t %
663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665 % GetMagickResourceLimit() returns the specified resource limit.
667 % The format of the GetMagickResourceLimit() method is:
669 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
671 % A description of each parameter follows:
673 % o type: the type of resource.
676 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
682 if (resource_semaphore == (SemaphoreInfo *) NULL)
683 ActivateSemaphoreInfo(&resource_semaphore);
684 LockSemaphoreInfo(resource_semaphore);
689 resource=resource_info.width_limit;
694 resource=resource_info.height_limit;
699 resource=resource_info.area_limit;
704 resource=resource_info.memory_limit;
709 resource=resource_info.map_limit;
714 resource=resource_info.disk_limit;
719 resource=resource_info.file_limit;
724 resource=resource_info.thread_limit;
727 case ThrottleResource:
729 resource=resource_info.throttle_limit;
734 resource=resource_info.time_limit;
740 UnlockSemaphoreInfo(resource_semaphore);
745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
749 % L i s t M a g i c k R e s o u r c e I n f o %
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755 % ListMagickResourceInfo() lists the resource info to a file.
757 % The format of the ListMagickResourceInfo method is:
759 % MagickBooleanType ListMagickResourceInfo(FILE *file,
760 % ExceptionInfo *exception)
762 % A description of each parameter follows.
764 % o file: An pointer to a FILE.
766 % o exception: return any errors or warnings in this structure.
769 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
770 ExceptionInfo *magick_unused(exception))
773 area_limit[MagickFormatExtent],
774 disk_limit[MagickFormatExtent],
775 height_limit[MagickFormatExtent],
776 map_limit[MagickFormatExtent],
777 memory_limit[MagickFormatExtent],
778 time_limit[MagickFormatExtent],
779 width_limit[MagickFormatExtent];
781 if (file == (const FILE *) NULL)
783 if (resource_semaphore == (SemaphoreInfo *) NULL)
784 ActivateSemaphoreInfo(&resource_semaphore);
785 LockSemaphoreInfo(resource_semaphore);
786 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
787 MagickFormatExtent,width_limit);
788 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
789 MagickFormatExtent,height_limit);
790 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
791 MagickFormatExtent,area_limit);
792 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
793 MagickFormatExtent,memory_limit);
794 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
795 MagickFormatExtent,map_limit);
796 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
797 if (resource_info.disk_limit != MagickResourceInfinity)
798 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
799 MagickFormatExtent,disk_limit);
800 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
801 if (resource_info.time_limit != MagickResourceInfinity)
802 (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
803 ((MagickOffsetType) resource_info.time_limit));
804 (void) FormatLocaleFile(file,"Resource limits:\n");
805 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
806 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
807 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
808 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
809 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
810 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
811 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
812 resource_info.file_limit));
813 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
814 resource_info.thread_limit));
815 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
816 ((MagickOffsetType) resource_info.throttle_limit));
817 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
819 UnlockSemaphoreInfo(resource_semaphore);
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
828 % R e l i n q u i s h M a g i c k R e s o u r c e %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 % RelinquishMagickResource() relinquishes resources of the specified type.
836 % The format of the RelinquishMagickResource() method is:
838 % void RelinquishMagickResource(const ResourceType type,
839 % const MagickSizeType size)
841 % A description of each parameter follows:
843 % o type: the type of resource.
845 % o size: the size of the resource.
848 MagickExport void RelinquishMagickResource(const ResourceType type,
849 const MagickSizeType size)
852 resource_current[MagickFormatExtent],
853 resource_limit[MagickFormatExtent],
854 resource_request[MagickFormatExtent];
856 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
858 if (resource_semaphore == (SemaphoreInfo *) NULL)
859 ActivateSemaphoreInfo(&resource_semaphore);
860 LockSemaphoreInfo(resource_semaphore);
865 resource_info.width=(MagickOffsetType) size;
866 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
867 "P",MagickFormatExtent,resource_current);
868 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
869 MagickFormatExtent,resource_limit);
874 resource_info.width=(MagickOffsetType) size;
875 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
876 "P",MagickFormatExtent,resource_current);
877 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
878 MagickFormatExtent,resource_limit);
883 resource_info.area=(MagickOffsetType) size;
884 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
885 "B",MagickFormatExtent,resource_current);
886 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
887 MagickFormatExtent,resource_limit);
892 resource_info.memory-=size;
893 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
894 MagickTrue,"B",MagickFormatExtent,resource_current);
895 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
896 MagickFormatExtent,resource_limit);
901 resource_info.map-=size;
902 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
903 "B",MagickFormatExtent,resource_current);
904 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
905 MagickFormatExtent,resource_limit);
910 resource_info.disk-=size;
911 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
912 "B",MagickFormatExtent,resource_current);
913 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
914 MagickFormatExtent,resource_limit);
919 resource_info.file-=size;
920 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
921 "B",MagickFormatExtent,resource_current);
922 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
923 MagickFalse,"B",MagickFormatExtent,resource_limit);
928 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
929 "B",MagickFormatExtent,resource_current);
930 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
931 MagickFalse,"B",MagickFormatExtent,resource_limit);
934 case ThrottleResource:
936 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
937 MagickFalse,"B",MagickFormatExtent,resource_current);
938 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
939 MagickFalse,"B",MagickFormatExtent,resource_limit);
944 resource_info.time-=size;
945 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
946 "B",MagickFormatExtent,resource_current);
947 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
948 MagickFalse,"B",MagickFormatExtent,resource_limit);
954 UnlockSemaphoreInfo(resource_semaphore);
955 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
956 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
957 resource_request,resource_current,resource_limit);
961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 % 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 %
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 % RelinquishUniqueFileResource() relinquishes a unique file resource.
973 % The format of the RelinquishUniqueFileResource() method is:
975 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
977 % A description of each parameter follows:
979 % o name: the name of the temporary resource.
982 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
985 cache_path[MagickPathExtent];
990 assert(path != (const char *) NULL);
992 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
993 if (resource_semaphore == (SemaphoreInfo *) NULL)
994 ActivateSemaphoreInfo(&resource_semaphore);
995 LockSemaphoreInfo(resource_semaphore);
996 if (temporary_resources != (SplayTreeInfo *) NULL)
997 status=DeleteNodeFromSplayTree(temporary_resources, (const void *) path);
998 UnlockSemaphoreInfo(resource_semaphore);
999 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1000 AppendImageFormat("cache",cache_path);
1001 (void) ShredFile(cache_path);
1002 if (status == MagickFalse)
1003 status=ShredFile(path);
1008 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 + R e s o u r c e C o m p o n e n t G e n e s i s %
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1018 % ResourceComponentGenesis() instantiates the resource component.
1020 % The format of the ResourceComponentGenesis method is:
1022 % MagickBooleanType ResourceComponentGenesis(void)
1026 static inline MagickSizeType StringToSizeType(const char *string,
1027 const double interval)
1032 value=SiPrefixToDoubleInterval(string,interval);
1033 if (value >= (double) MagickULLConstant(~0))
1034 return(MagickULLConstant(~0));
1035 return((MagickSizeType) value);
1038 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1052 Set Magick resource limits.
1054 if (resource_semaphore == (SemaphoreInfo *) NULL)
1055 resource_semaphore=AcquireSemaphoreInfo();
1056 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1057 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1058 if (limit != (char *) NULL)
1060 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1062 limit=DestroyString(limit);
1064 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1065 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1066 if (limit != (char *) NULL)
1068 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1070 limit=DestroyString(limit);
1072 pagesize=GetMagickPageSize();
1074 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1075 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1077 memory=(MagickSizeType) pages*pagesize;
1078 if ((pagesize <= 0) || (pages <= 0))
1079 memory=2048UL*1024UL*1024UL;
1080 #if defined(PixelCacheThreshold)
1081 memory=PixelCacheThreshold;
1083 (void) SetMagickResourceLimit(AreaResource,2*memory);
1084 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1085 if (limit != (char *) NULL)
1087 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1088 limit=DestroyString(limit);
1090 (void) SetMagickResourceLimit(MemoryResource,memory);
1091 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1092 if (limit != (char *) NULL)
1094 (void) SetMagickResourceLimit(MemoryResource,
1095 StringToSizeType(limit,100.0));
1096 limit=DestroyString(limit);
1098 (void) SetMagickResourceLimit(MapResource,2*memory);
1099 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1100 if (limit != (char *) NULL)
1102 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1103 limit=DestroyString(limit);
1105 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1106 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1107 if (limit != (char *) NULL)
1109 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1110 limit=DestroyString(limit);
1113 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1114 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1116 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1122 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1123 files=(ssize_t) resources.rlim_cur;
1126 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1128 files=(ssize_t) getdtablesize();
1132 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1134 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1135 if (limit != (char *) NULL)
1137 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1139 limit=DestroyString(limit);
1141 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1142 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1143 if (limit != (char *) NULL)
1145 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1147 limit=DestroyString(limit);
1149 (void) SetMagickResourceLimit(ThrottleResource,0);
1150 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1151 if (limit != (char *) NULL)
1153 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1155 limit=DestroyString(limit);
1157 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1158 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1159 if (limit != (char *) NULL)
1161 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1162 limit=DestroyString(limit);
1168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 + 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 %
1176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1178 % ResourceComponentTerminus() destroys the resource component.
1180 % The format of the ResourceComponentTerminus() method is:
1182 % ResourceComponentTerminus(void)
1185 MagickPrivate void ResourceComponentTerminus(void)
1187 if (resource_semaphore == (SemaphoreInfo *) NULL)
1188 resource_semaphore=AcquireSemaphoreInfo();
1189 LockSemaphoreInfo(resource_semaphore);
1190 if (temporary_resources != (SplayTreeInfo *) NULL)
1191 temporary_resources=DestroySplayTree(temporary_resources);
1192 if (random_info != (RandomInfo *) NULL)
1193 random_info=DestroyRandomInfo(random_info);
1194 UnlockSemaphoreInfo(resource_semaphore);
1195 RelinquishSemaphoreInfo(&resource_semaphore);
1199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1203 % S e t M a g i c k R e s o u r c e L i m i t %
1207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209 % SetMagickResourceLimit() sets the limit for a particular resource.
1211 % The format of the SetMagickResourceLimit() method is:
1213 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1214 % const MagickSizeType limit)
1216 % A description of each parameter follows:
1218 % o type: the type of resource.
1220 % o limit: the maximum limit for the resource.
1224 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1225 const MagickSizeType limit)
1230 if (resource_semaphore == (SemaphoreInfo *) NULL)
1231 resource_semaphore=AcquireSemaphoreInfo();
1232 LockSemaphoreInfo(resource_semaphore);
1233 value=(char *) NULL;
1238 resource_info.width_limit=limit;
1239 value=GetPolicyValue("width");
1240 if (value != (char *) NULL)
1241 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1245 case HeightResource:
1247 resource_info.height_limit=limit;
1248 value=GetPolicyValue("height");
1249 if (value != (char *) NULL)
1250 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1256 resource_info.area_limit=limit;
1257 value=GetPolicyValue("area");
1258 if (value != (char *) NULL)
1259 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1262 case MemoryResource:
1264 resource_info.memory_limit=limit;
1265 value=GetPolicyValue("memory");
1266 if (value != (char *) NULL)
1267 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1273 resource_info.map_limit=limit;
1274 value=GetPolicyValue("map");
1275 if (value != (char *) NULL)
1276 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1281 resource_info.disk_limit=limit;
1282 value=GetPolicyValue("disk");
1283 if (value != (char *) NULL)
1284 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1289 resource_info.file_limit=limit;
1290 value=GetPolicyValue("file");
1291 if (value != (char *) NULL)
1292 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1295 case ThreadResource:
1297 resource_info.thread_limit=limit;
1298 value=GetPolicyValue("thread");
1299 if (value != (char *) NULL)
1300 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1302 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1303 resource_info.thread_limit=GetOpenMPMaximumThreads();
1304 else if (resource_info.thread_limit == 0)
1305 resource_info.thread_limit=1;
1308 case ThrottleResource:
1310 resource_info.throttle_limit=limit;
1311 value=GetPolicyValue("throttle");
1312 if (value != (char *) NULL)
1313 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value,
1315 if (resource_info.throttle_limit > GetOpenMPMaximumThreads())
1316 resource_info.throttle_limit=GetOpenMPMaximumThreads();
1321 resource_info.time_limit=limit;
1322 value=GetPolicyValue("time");
1323 if (value != (char *) NULL)
1324 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1330 if (value != (char *) NULL)
1331 value=DestroyString(value);
1332 UnlockSemaphoreInfo(resource_semaphore);