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-2017 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 % https://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/cache-private.h"
45 #include "MagickCore/configure.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/linked-list.h"
49 #include "MagickCore/log.h"
50 #include "MagickCore/image.h"
51 #include "MagickCore/image-private.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/nt-base-private.h"
54 #include "MagickCore/option.h"
55 #include "MagickCore/policy.h"
56 #include "MagickCore/random_.h"
57 #include "MagickCore/registry.h"
58 #include "MagickCore/resource_.h"
59 #include "MagickCore/resource-private.h"
60 #include "MagickCore/semaphore.h"
61 #include "MagickCore/signature-private.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/string-private.h"
64 #include "MagickCore/splay-tree.h"
65 #include "MagickCore/thread-private.h"
66 #include "MagickCore/token.h"
67 #include "MagickCore/utility.h"
68 #include "MagickCore/utility-private.h"
73 #define MagickPathTemplate "XXXXXXXXXXXX"
78 typedef struct _ResourceInfo
109 *random_info = (RandomInfo *) NULL;
114 MagickULLConstant(0), /* initial width */
115 MagickULLConstant(0), /* initial height */
116 MagickULLConstant(0), /* initial area */
117 MagickULLConstant(0), /* initial memory */
118 MagickULLConstant(0), /* initial map */
119 MagickULLConstant(0), /* initial disk */
120 MagickULLConstant(0), /* initial file */
121 MagickULLConstant(0), /* initial thread */
122 MagickULLConstant(0), /* initial throttle */
123 MagickULLConstant(0), /* initial time */
124 (INT_MAX/(5*sizeof(Quantum))), /* width limit */
125 (INT_MAX/(5*sizeof(Quantum))), /* height limit */
126 MagickULLConstant(3072)*1024*1024, /* area limit */
127 MagickULLConstant(1536)*1024*1024, /* memory limit */
128 MagickULLConstant(3072)*1024*1024, /* map limit */
129 MagickResourceInfinity, /* disk limit */
130 MagickULLConstant(768), /* file limit */
131 MagickULLConstant(1), /* thread limit */
132 MagickULLConstant(0), /* throttle limit */
133 MagickResourceInfinity /* time limit */
137 *resource_semaphore = (SemaphoreInfo *) NULL;
140 *temporary_resources = (SplayTreeInfo *) NULL;
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147 % A c q u i r e M a g i c k R e s o u r c e %
151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153 % AcquireMagickResource() acquires resources of the specified type.
154 % MagickFalse is returned if the specified resource is exhausted otherwise
157 % The format of the AcquireMagickResource() method is:
159 % MagickBooleanType AcquireMagickResource(const ResourceType type,
160 % const MagickSizeType size)
162 % A description of each parameter follows:
164 % o type: the type of resource.
166 % o size: the number of bytes needed from for this resource.
169 MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type,
170 const MagickSizeType size)
173 resource_current[MagickFormatExtent],
174 resource_limit[MagickFormatExtent],
175 resource_request[MagickFormatExtent];
184 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
186 if (resource_semaphore == (SemaphoreInfo *) NULL)
187 ActivateSemaphoreInfo(&resource_semaphore);
188 LockSemaphoreInfo(resource_semaphore);
193 resource_info.area=(MagickOffsetType) size;
194 limit=resource_info.area_limit;
195 status=(resource_info.area_limit == MagickResourceInfinity) ||
196 (size < limit) ? MagickTrue : MagickFalse;
197 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
198 "P",MagickFormatExtent,resource_current);
199 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
200 MagickFormatExtent,resource_limit);
205 resource_info.memory+=size;
206 limit=resource_info.memory_limit;
207 status=(resource_info.memory_limit == MagickResourceInfinity) ||
208 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue :
210 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue,
211 "B",MagickFormatExtent,resource_current);
212 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
213 MagickFormatExtent,resource_limit);
218 resource_info.map+=size;
219 limit=resource_info.map_limit;
220 status=(resource_info.map_limit == MagickResourceInfinity) ||
221 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse;
222 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
223 "B",MagickFormatExtent,resource_current);
224 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
225 MagickFormatExtent,resource_limit);
230 resource_info.disk+=size;
231 limit=resource_info.disk_limit;
232 status=(resource_info.disk_limit == MagickResourceInfinity) ||
233 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue :
235 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
236 "B",MagickFormatExtent,resource_current);
237 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
238 MagickFormatExtent,resource_limit);
243 resource_info.file+=size;
244 limit=resource_info.file_limit;
245 status=(resource_info.file_limit == MagickResourceInfinity) ||
246 ((MagickSizeType) resource_info.file < limit) ?
247 MagickTrue : MagickFalse;
248 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
249 "B",MagickFormatExtent,resource_current);
250 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
251 MagickFalse,"B",MagickFormatExtent,resource_limit);
256 resource_info.area=(MagickOffsetType) size;
257 limit=resource_info.height_limit;
258 status=(resource_info.area_limit == MagickResourceInfinity) ||
259 (size < limit) ? MagickTrue : MagickFalse;
260 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
261 "P",MagickFormatExtent,resource_current);
262 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
263 MagickFormatExtent,resource_limit);
268 limit=resource_info.thread_limit;
269 status=(resource_info.thread_limit == MagickResourceInfinity) ||
270 ((MagickSizeType) resource_info.thread < limit) ?
271 MagickTrue : MagickFalse;
272 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
273 "B",MagickFormatExtent,resource_current);
274 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
275 MagickFalse,"B",MagickFormatExtent,resource_limit);
278 case ThrottleResource:
280 limit=resource_info.throttle_limit;
281 status=(resource_info.throttle_limit == MagickResourceInfinity) ||
282 ((MagickSizeType) resource_info.throttle < limit) ?
283 MagickTrue : MagickFalse;
284 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
285 MagickFalse,"B",MagickFormatExtent,resource_current);
286 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
287 MagickFalse,"B",MagickFormatExtent,resource_limit);
292 resource_info.time+=size;
293 limit=resource_info.time_limit;
294 status=(resource_info.time_limit == MagickResourceInfinity) ||
295 ((MagickSizeType) resource_info.time < limit) ?
296 MagickTrue : MagickFalse;
297 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
298 "B",MagickFormatExtent,resource_current);
299 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
300 MagickFalse,"B",MagickFormatExtent,resource_limit);
305 resource_info.area=(MagickOffsetType) size;
306 limit=resource_info.width_limit;
307 status=(resource_info.area_limit == MagickResourceInfinity) ||
308 (size < limit) ? MagickTrue : MagickFalse;
309 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
310 "P",MagickFormatExtent,resource_current);
311 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
312 MagickFormatExtent,resource_limit);
318 UnlockSemaphoreInfo(resource_semaphore);
319 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
320 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
321 resource_request,resource_current,resource_limit);
326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330 + 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 %
334 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 % AsynchronousResourceComponentTerminus() destroys the resource environment.
337 % It differs from ResourceComponentTerminus() in that it can be called from a
338 % asynchronous signal handler.
340 % The format of the ResourceComponentTerminus() method is:
342 % ResourceComponentTerminus(void)
345 MagickPrivate void AsynchronousResourceComponentTerminus(void)
350 if (temporary_resources == (SplayTreeInfo *) NULL)
353 Remove any lingering temporary files.
355 ResetSplayTreeIterator(temporary_resources);
356 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
357 while (path != (const char *) NULL)
359 (void) ShredFile(path);
360 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 % 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 %
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 % AcquireUniqueFileResource() returns a unique file name, and returns a file
376 % descriptor for the file open for reading and writing.
378 % The format of the AcquireUniqueFileResource() method is:
380 % int AcquireUniqueFileResource(char *path)
382 % A description of each parameter follows:
384 % o path: Specifies a pointer to an array of characters. The unique path
385 % name is returned in this array.
389 static void *DestroyTemporaryResources(void *temporary_resource)
391 (void) ShredFile((char *) temporary_resource);
392 temporary_resource=DestroyString((char *) temporary_resource);
393 return((void *) NULL);
396 MagickExport MagickBooleanType GetPathTemplate(char *path)
411 (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20g"
412 MagickPathTemplate,(double) getpid());
413 exception=AcquireExceptionInfo();
414 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
416 exception=DestroyExceptionInfo(exception);
417 if (directory == (char *) NULL)
418 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
419 if (directory == (char *) NULL)
420 directory=GetEnvironmentValue("MAGICK_TMPDIR");
421 if (directory == (char *) NULL)
422 directory=GetEnvironmentValue("TMPDIR");
423 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
424 if (directory == (char *) NULL)
425 directory=GetEnvironmentValue("TMP");
426 if (directory == (char *) NULL)
427 directory=GetEnvironmentValue("TEMP");
430 if (directory == (char *) NULL)
431 directory=GetEnvironmentValue("MTMPDIR");
433 #if defined(P_tmpdir)
434 if (directory == (char *) NULL)
435 directory=ConstantString(P_tmpdir);
437 if (directory == (char *) NULL)
439 value=GetPolicyValue("resource:temporary-path");
440 if (value != (char *) NULL)
442 (void) CloneString(&directory,value);
443 value=DestroyString(value);
445 if (strlen(directory) > (MagickPathExtent-25))
447 directory=DestroyString(directory);
450 status=GetPathAttributes(directory,&attributes);
451 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
453 directory=DestroyString(directory);
456 if (directory[strlen(directory)-1] == *DirectorySeparator)
457 (void) FormatLocaleString(path,MagickPathExtent,
458 "%smagick-%.20g" MagickPathTemplate,directory,(double) getpid());
460 (void) FormatLocaleString(path,MagickPathExtent,
461 "%s%smagick-%.20g" MagickPathTemplate,directory,DirectorySeparator,
463 directory=DestroyString(directory);
464 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
470 Ghostscript does not like backslashes so we need to replace them. The
471 forward slash also works under Windows.
473 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
474 if (*p == *DirectorySeparator)
481 MagickExport int AcquireUniqueFileResource(char *path)
483 #if !defined(O_NOFOLLOW)
486 #if !defined(TMP_MAX)
487 # define TMP_MAX 238328
501 portable_filename[65] =
502 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
510 assert(path != (char *) NULL);
511 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
512 if (random_info == (RandomInfo *) NULL)
514 LockSemaphoreInfo(resource_semaphore);
515 if (random_info == (RandomInfo *) NULL)
516 random_info=AcquireRandomInfo();
517 UnlockSemaphoreInfo(resource_semaphore);
520 for (i=0; i < (ssize_t) TMP_MAX; i++)
523 Get temporary pathname.
525 (void) GetPathTemplate(path);
526 key=GetRandomKey(random_info,6);
527 p=path+strlen(path)-strlen(MagickPathTemplate);
528 datum=GetStringInfoDatum(key);
529 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
531 c=(int) (datum[i] & 0x3f);
532 *p++=portable_filename[c];
534 key=DestroyStringInfo(key);
535 #if defined(MAGICKCORE_HAVE_MKSTEMP)
539 #if defined(MAGICKCORE_HAVE_FCHMOD)
540 (void) fchmod(file,0600);
543 setmode(file,O_BINARY);
548 key=GetRandomKey(random_info,strlen(MagickPathTemplate));
549 p=path+strlen(path)-strlen(MagickPathTemplate);
550 datum=GetStringInfoDatum(key);
551 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++)
553 c=(int) (datum[i] & 0x3f);
554 *p++=portable_filename[c];
556 key=DestroyStringInfo(key);
557 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
559 if ((file >= 0) || (errno != EEXIST))
562 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
565 if (resource_semaphore == (SemaphoreInfo *) NULL)
566 ActivateSemaphoreInfo(&resource_semaphore);
567 LockSemaphoreInfo(resource_semaphore);
568 if (temporary_resources == (SplayTreeInfo *) NULL)
569 temporary_resources=NewSplayTree(CompareSplayTreeString,
570 DestroyTemporaryResources,(void *(*)(void *)) NULL);
571 UnlockSemaphoreInfo(resource_semaphore);
572 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
573 (const void *) NULL);
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 % G e t M a g i c k R e s o u r c e %
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 % GetMagickResource() returns the specified resource.
590 % The format of the GetMagickResource() method is:
592 % MagickSizeType GetMagickResource(const ResourceType type)
594 % A description of each parameter follows:
596 % o type: the type of resource.
599 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
605 LockSemaphoreInfo(resource_semaphore);
610 resource=(MagickSizeType) resource_info.width;
615 resource=(MagickSizeType) resource_info.height;
620 resource=(MagickSizeType) resource_info.area;
625 resource=(MagickSizeType) resource_info.memory;
630 resource=(MagickSizeType) resource_info.map;
635 resource=(MagickSizeType) resource_info.disk;
640 resource=(MagickSizeType) resource_info.file;
645 resource=(MagickSizeType) resource_info.thread;
648 case ThrottleResource:
650 resource=(MagickSizeType) resource_info.throttle;
655 resource=(MagickSizeType) resource_info.time;
661 UnlockSemaphoreInfo(resource_semaphore);
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670 % G e t M a g i c k R e s o u r c e L i m i t %
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
676 % GetMagickResourceLimit() returns the specified resource limit.
678 % The format of the GetMagickResourceLimit() method is:
680 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
682 % A description of each parameter follows:
684 % o type: the type of resource.
687 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
693 if (resource_semaphore == (SemaphoreInfo *) NULL)
694 ActivateSemaphoreInfo(&resource_semaphore);
695 LockSemaphoreInfo(resource_semaphore);
700 resource=resource_info.width_limit;
705 resource=resource_info.height_limit;
710 resource=resource_info.area_limit;
715 resource=resource_info.memory_limit;
720 resource=resource_info.map_limit;
725 resource=resource_info.disk_limit;
730 resource=resource_info.file_limit;
735 resource=resource_info.thread_limit;
738 case ThrottleResource:
740 resource=resource_info.throttle_limit;
745 resource=resource_info.time_limit;
751 UnlockSemaphoreInfo(resource_semaphore);
756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 % L i s t M a g i c k R e s o u r c e I n f o %
764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
766 % ListMagickResourceInfo() lists the resource info to a file.
768 % The format of the ListMagickResourceInfo method is:
770 % MagickBooleanType ListMagickResourceInfo(FILE *file,
771 % ExceptionInfo *exception)
773 % A description of each parameter follows.
775 % o file: An pointer to a FILE.
777 % o exception: return any errors or warnings in this structure.
780 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
781 ExceptionInfo *magick_unused(exception))
784 area_limit[MagickFormatExtent],
785 disk_limit[MagickFormatExtent],
786 height_limit[MagickFormatExtent],
787 map_limit[MagickFormatExtent],
788 memory_limit[MagickFormatExtent],
789 time_limit[MagickFormatExtent],
790 width_limit[MagickFormatExtent];
792 magick_unreferenced(exception);
794 if (file == (const FILE *) NULL)
796 if (resource_semaphore == (SemaphoreInfo *) NULL)
797 ActivateSemaphoreInfo(&resource_semaphore);
798 LockSemaphoreInfo(resource_semaphore);
799 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
800 MagickFormatExtent,width_limit);
801 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
802 MagickFormatExtent,height_limit);
803 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
804 MagickFormatExtent,area_limit);
805 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
806 MagickFormatExtent,memory_limit);
807 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
808 MagickFormatExtent,map_limit);
809 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
810 if (resource_info.disk_limit != MagickResourceInfinity)
811 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
812 MagickFormatExtent,disk_limit);
813 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
814 if (resource_info.time_limit != MagickResourceInfinity)
815 (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
816 ((MagickOffsetType) resource_info.time_limit));
817 (void) FormatLocaleFile(file,"Resource limits:\n");
818 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
819 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
820 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
821 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
822 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
823 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
824 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
825 resource_info.file_limit));
826 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
827 resource_info.thread_limit));
828 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
829 ((MagickOffsetType) resource_info.throttle_limit));
830 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
832 UnlockSemaphoreInfo(resource_semaphore);
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 % R e l i n q u i s h M a g i c k R e s o u r c e %
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847 % RelinquishMagickResource() relinquishes resources of the specified type.
849 % The format of the RelinquishMagickResource() method is:
851 % void RelinquishMagickResource(const ResourceType type,
852 % const MagickSizeType size)
854 % A description of each parameter follows:
856 % o type: the type of resource.
858 % o size: the size of the resource.
861 MagickExport void RelinquishMagickResource(const ResourceType type,
862 const MagickSizeType size)
865 resource_current[MagickFormatExtent],
866 resource_limit[MagickFormatExtent],
867 resource_request[MagickFormatExtent];
869 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
871 if (resource_semaphore == (SemaphoreInfo *) NULL)
872 ActivateSemaphoreInfo(&resource_semaphore);
873 LockSemaphoreInfo(resource_semaphore);
878 resource_info.width=(MagickOffsetType) size;
879 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse,
880 "P",MagickFormatExtent,resource_current);
881 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
882 MagickFormatExtent,resource_limit);
887 resource_info.height=(MagickOffsetType) size;
888 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse,
889 "P",MagickFormatExtent,resource_current);
890 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
891 MagickFormatExtent,resource_limit);
896 resource_info.area=(MagickOffsetType) size;
897 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse,
898 "B",MagickFormatExtent,resource_current);
899 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B",
900 MagickFormatExtent,resource_limit);
905 resource_info.memory-=size;
906 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
907 MagickTrue,"B",MagickFormatExtent,resource_current);
908 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
909 MagickFormatExtent,resource_limit);
914 resource_info.map-=size;
915 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue,
916 "B",MagickFormatExtent,resource_current);
917 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
918 MagickFormatExtent,resource_limit);
923 resource_info.disk-=size;
924 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue,
925 "B",MagickFormatExtent,resource_current);
926 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
927 MagickFormatExtent,resource_limit);
932 resource_info.file-=size;
933 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse,
934 "B",MagickFormatExtent,resource_current);
935 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
936 MagickFalse,"B",MagickFormatExtent,resource_limit);
941 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse,
942 "B",MagickFormatExtent,resource_current);
943 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
944 MagickFalse,"B",MagickFormatExtent,resource_limit);
947 case ThrottleResource:
949 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
950 MagickFalse,"B",MagickFormatExtent,resource_current);
951 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
952 MagickFalse,"B",MagickFormatExtent,resource_limit);
957 resource_info.time-=size;
958 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse,
959 "B",MagickFormatExtent,resource_current);
960 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
961 MagickFalse,"B",MagickFormatExtent,resource_limit);
967 UnlockSemaphoreInfo(resource_semaphore);
968 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
969 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
970 resource_request,resource_current,resource_limit);
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 % 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 %
982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984 % RelinquishUniqueFileResource() relinquishes a unique file resource.
986 % The format of the RelinquishUniqueFileResource() method is:
988 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
990 % A description of each parameter follows:
992 % o name: the name of the temporary resource.
995 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
998 cache_path[MagickPathExtent];
1003 assert(path != (const char *) NULL);
1005 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1006 if (resource_semaphore == (SemaphoreInfo *) NULL)
1007 ActivateSemaphoreInfo(&resource_semaphore);
1008 LockSemaphoreInfo(resource_semaphore);
1009 if (temporary_resources != (SplayTreeInfo *) NULL)
1010 status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
1011 UnlockSemaphoreInfo(resource_semaphore);
1012 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1013 AppendImageFormat("cache",cache_path);
1014 (void) ShredFile(cache_path);
1015 if (status == MagickFalse)
1016 status=ShredFile(path);
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 + R e s o u r c e C o m p o n e n t G e n e s i s %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031 % ResourceComponentGenesis() instantiates the resource component.
1033 % The format of the ResourceComponentGenesis method is:
1035 % MagickBooleanType ResourceComponentGenesis(void)
1039 static inline MagickSizeType StringToSizeType(const char *string,
1040 const double interval)
1045 value=SiPrefixToDoubleInterval(string,interval);
1046 if (value >= (double) MagickULLConstant(~0))
1047 return(MagickULLConstant(~0));
1048 return((MagickSizeType) value);
1051 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1065 Set Magick resource limits.
1067 if (resource_semaphore == (SemaphoreInfo *) NULL)
1068 resource_semaphore=AcquireSemaphoreInfo();
1069 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1070 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1071 if (limit != (char *) NULL)
1073 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1075 limit=DestroyString(limit);
1077 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1078 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1079 if (limit != (char *) NULL)
1081 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1083 limit=DestroyString(limit);
1085 pagesize=GetMagickPageSize();
1087 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1088 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1090 memory=(MagickSizeType) pages*pagesize;
1091 if ((pagesize <= 0) || (pages <= 0))
1092 memory=2048UL*1024UL*1024UL;
1093 #if defined(PixelCacheThreshold)
1094 memory=PixelCacheThreshold;
1096 (void) SetMagickResourceLimit(AreaResource,2*memory);
1097 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1098 if (limit != (char *) NULL)
1100 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1101 limit=DestroyString(limit);
1103 (void) SetMagickResourceLimit(MemoryResource,memory);
1104 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1105 if (limit != (char *) NULL)
1107 (void) SetMagickResourceLimit(MemoryResource,
1108 StringToSizeType(limit,100.0));
1109 limit=DestroyString(limit);
1111 (void) SetMagickResourceLimit(MapResource,2*memory);
1112 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1113 if (limit != (char *) NULL)
1115 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1116 limit=DestroyString(limit);
1118 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1119 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1120 if (limit != (char *) NULL)
1122 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1123 limit=DestroyString(limit);
1126 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1127 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1129 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1135 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1136 files=(ssize_t) resources.rlim_cur;
1139 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1141 files=(ssize_t) getdtablesize();
1145 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1147 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1148 if (limit != (char *) NULL)
1150 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1152 limit=DestroyString(limit);
1154 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1155 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1156 if (limit != (char *) NULL)
1158 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1160 limit=DestroyString(limit);
1162 (void) SetMagickResourceLimit(ThrottleResource,0);
1163 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1164 if (limit != (char *) NULL)
1166 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1168 limit=DestroyString(limit);
1170 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1171 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1172 if (limit != (char *) NULL)
1174 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1175 limit=DestroyString(limit);
1181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 + 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 %
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1191 % ResourceComponentTerminus() destroys the resource component.
1193 % The format of the ResourceComponentTerminus() method is:
1195 % ResourceComponentTerminus(void)
1198 MagickPrivate void ResourceComponentTerminus(void)
1200 if (resource_semaphore == (SemaphoreInfo *) NULL)
1201 resource_semaphore=AcquireSemaphoreInfo();
1202 LockSemaphoreInfo(resource_semaphore);
1203 if (temporary_resources != (SplayTreeInfo *) NULL)
1204 temporary_resources=DestroySplayTree(temporary_resources);
1205 if (random_info != (RandomInfo *) NULL)
1206 random_info=DestroyRandomInfo(random_info);
1207 UnlockSemaphoreInfo(resource_semaphore);
1208 RelinquishSemaphoreInfo(&resource_semaphore);
1212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216 % S e t M a g i c k R e s o u r c e L i m i t %
1220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1222 % SetMagickResourceLimit() sets the limit for a particular resource.
1224 % The format of the SetMagickResourceLimit() method is:
1226 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1227 % const MagickSizeType limit)
1229 % A description of each parameter follows:
1231 % o type: the type of resource.
1233 % o limit: the maximum limit for the resource.
1237 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1238 const MagickSizeType limit)
1243 if (resource_semaphore == (SemaphoreInfo *) NULL)
1244 resource_semaphore=AcquireSemaphoreInfo();
1245 LockSemaphoreInfo(resource_semaphore);
1246 value=(char *) NULL;
1251 resource_info.width_limit=limit;
1252 value=GetPolicyValue("resource:width");
1253 if (value != (char *) NULL)
1254 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1258 case HeightResource:
1260 resource_info.height_limit=limit;
1261 value=GetPolicyValue("resource:height");
1262 if (value != (char *) NULL)
1263 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1269 resource_info.area_limit=limit;
1270 value=GetPolicyValue("resource:area");
1271 if (value != (char *) NULL)
1272 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1275 case MemoryResource:
1277 resource_info.memory_limit=limit;
1278 value=GetPolicyValue("resource:memory");
1279 if (value != (char *) NULL)
1280 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1286 resource_info.map_limit=limit;
1287 value=GetPolicyValue("resource:map");
1288 if (value != (char *) NULL)
1289 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1294 resource_info.disk_limit=limit;
1295 value=GetPolicyValue("resource:disk");
1296 if (value != (char *) NULL)
1297 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1302 resource_info.file_limit=limit;
1303 value=GetPolicyValue("resource:file");
1304 if (value != (char *) NULL)
1305 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1308 case ThreadResource:
1310 resource_info.thread_limit=limit;
1311 value=GetPolicyValue("resource:thread");
1312 if (value != (char *) NULL)
1313 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1315 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1316 resource_info.thread_limit=GetOpenMPMaximumThreads();
1318 if (resource_info.thread_limit == 0)
1319 resource_info.thread_limit=1;
1322 case ThrottleResource:
1324 resource_info.throttle_limit=limit;
1325 value=GetPolicyValue("resource:throttle");
1326 if (value != (char *) NULL)
1327 resource_info.throttle_limit=MagickMax(limit,StringToSizeType(value,
1333 resource_info.time_limit=limit;
1334 value=GetPolicyValue("resource:time");
1335 if (value != (char *) NULL)
1336 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1337 ResetPixelCacheEpoch();
1343 if (value != (char *) NULL)
1344 value=DestroyString(value);
1345 UnlockSemaphoreInfo(resource_semaphore);