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];
185 logging=IsEventLogging();
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 if ((limit == MagickResourceInfinity) || (size < limit))
197 if (logging != MagickFalse)
199 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
200 MagickFormatExtent,resource_request);
201 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
202 MagickFormatExtent,resource_current);
203 (void) FormatMagickSize(limit,MagickFalse,(const char *) NULL,
204 MagickFormatExtent,resource_limit);
210 resource_info.memory+=(MagickOffsetType) size;
211 limit=resource_info.memory_limit;
212 if ((limit == MagickResourceInfinity) ||
213 (resource_info.memory < (MagickOffsetType) limit))
216 resource_info.memory-=(MagickOffsetType) size;
217 if (logging != MagickFalse)
219 (void) FormatMagickSize(size,MagickTrue,"B",MagickFormatExtent,
221 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
222 MagickTrue,"B",MagickFormatExtent,resource_current);
223 (void) FormatMagickSize(limit,MagickTrue,"B",MagickFormatExtent,
230 resource_info.map+=(MagickOffsetType) size;
231 limit=resource_info.map_limit;
232 if ((limit == MagickResourceInfinity) ||
233 (resource_info.map < (MagickOffsetType) limit))
236 resource_info.map-=(MagickOffsetType) size;
237 if (logging != MagickFalse)
239 (void) FormatMagickSize(size,MagickTrue,"B",MagickFormatExtent,
241 (void) FormatMagickSize((MagickSizeType) resource_info.map,
242 MagickTrue,"B",MagickFormatExtent,resource_current);
243 (void) FormatMagickSize(limit,MagickTrue,"B",MagickFormatExtent,
250 resource_info.disk+=(MagickOffsetType) size;
251 limit=resource_info.disk_limit;
252 if ((limit == MagickResourceInfinity) ||
253 (resource_info.disk < (MagickOffsetType) limit))
256 resource_info.disk-=(MagickOffsetType) size;
257 if (logging != MagickFalse)
259 (void) FormatMagickSize(size,MagickTrue,"B",MagickFormatExtent,
261 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
262 MagickTrue,"B",MagickFormatExtent,resource_current);
263 (void) FormatMagickSize(limit,MagickTrue,"B",MagickFormatExtent,
270 resource_info.file+=(MagickOffsetType) size;
271 limit=resource_info.file_limit;
272 if ((limit == MagickResourceInfinity) ||
273 (resource_info.file < (MagickOffsetType) limit))
276 resource_info.file-=(MagickOffsetType) size;
277 if (logging != MagickFalse)
279 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
280 MagickFormatExtent,resource_request);
281 (void) FormatMagickSize((MagickSizeType) resource_info.file,
282 MagickFalse,(const char *) NULL,MagickFormatExtent,
284 (void) FormatMagickSize(limit,MagickTrue,(const char *) NULL,
285 MagickFormatExtent,resource_limit);
291 resource_info.height=(MagickOffsetType) size;
292 limit=resource_info.height_limit;
293 if ((limit == MagickResourceInfinity) || (size < limit))
295 if (logging != MagickFalse)
297 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
299 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
301 (void) FormatMagickSize(limit,MagickFalse,"P",MagickFormatExtent,
308 limit=resource_info.thread_limit;
309 if ((limit == MagickResourceInfinity) ||
310 (resource_info.thread < (MagickOffsetType) limit))
312 if (logging != MagickFalse)
314 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
315 MagickFormatExtent,resource_request);
316 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
317 MagickFalse,(const char *) NULL,MagickFormatExtent,
319 (void) FormatMagickSize(limit,MagickFalse,(const char *) NULL,
320 MagickFormatExtent,resource_limit);
324 case ThrottleResource:
326 limit=resource_info.throttle_limit;
327 if ((limit == MagickResourceInfinity) ||
328 (resource_info.throttle < (MagickOffsetType) limit))
330 if (logging != MagickFalse)
332 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
333 MagickFormatExtent,resource_request);
334 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
335 MagickFalse,(const char *) NULL,MagickFormatExtent,
337 (void) FormatMagickSize(limit,MagickFalse,(const char *) NULL,
338 MagickFormatExtent,resource_limit);
344 resource_info.time+=(MagickOffsetType) size;
345 limit=resource_info.time_limit;
346 if ((limit == MagickResourceInfinity) ||
347 (resource_info.time < (MagickOffsetType) limit))
350 resource_info.time-=(MagickOffsetType) size;
351 if (logging != MagickFalse)
353 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
354 MagickFormatExtent,resource_request);
355 (void) FormatMagickSize((MagickSizeType) resource_info.time,
356 MagickFalse,(const char *) NULL,MagickFormatExtent,
358 (void) FormatMagickSize(limit,MagickFalse,(const char *) NULL,
359 MagickFormatExtent,resource_limit);
365 resource_info.width=(MagickOffsetType) size;
366 limit=resource_info.width_limit;
367 if ((limit == MagickResourceInfinity) || (size < limit))
369 if (logging != MagickFalse)
371 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
373 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
375 (void) FormatMagickSize(limit,MagickFalse,"P",MagickFormatExtent,
383 UnlockSemaphoreInfo(resource_semaphore);
384 if (logging != MagickFalse)
386 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
387 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
388 resource_request,resource_current,resource_limit);
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 + 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 %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
404 % AsynchronousResourceComponentTerminus() destroys the resource environment.
405 % It differs from ResourceComponentTerminus() in that it can be called from a
406 % asynchronous signal handler.
408 % The format of the ResourceComponentTerminus() method is:
410 % ResourceComponentTerminus(void)
413 MagickPrivate void AsynchronousResourceComponentTerminus(void)
418 if (temporary_resources == (SplayTreeInfo *) NULL)
421 Remove any lingering temporary files.
423 ResetSplayTreeIterator(temporary_resources);
424 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
425 while (path != (const char *) NULL)
427 (void) ShredFile(path);
428 path=(const char *) GetNextKeyInSplayTree(temporary_resources);
433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
437 % 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 %
441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 % AcquireUniqueFileResource() returns a unique file name, and returns a file
444 % descriptor for the file open for reading and writing.
446 % The format of the AcquireUniqueFileResource() method is:
448 % int AcquireUniqueFileResource(char *path)
450 % A description of each parameter follows:
452 % o path: Specifies a pointer to an array of characters. The unique path
453 % name is returned in this array.
457 static void *DestroyTemporaryResources(void *temporary_resource)
459 (void) ShredFile((char *) temporary_resource);
460 temporary_resource=DestroyString((char *) temporary_resource);
461 return((void *) NULL);
464 MagickExport MagickBooleanType GetPathTemplate(char *path)
479 (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20g"
480 MagickPathTemplate,(double) getpid());
481 exception=AcquireExceptionInfo();
482 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path",
484 exception=DestroyExceptionInfo(exception);
485 if (directory == (char *) NULL)
486 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH");
487 if (directory == (char *) NULL)
488 directory=GetEnvironmentValue("MAGICK_TMPDIR");
489 if (directory == (char *) NULL)
490 directory=GetEnvironmentValue("TMPDIR");
491 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__)
492 if (directory == (char *) NULL)
493 directory=GetEnvironmentValue("TMP");
494 if (directory == (char *) NULL)
495 directory=GetEnvironmentValue("TEMP");
498 if (directory == (char *) NULL)
499 directory=GetEnvironmentValue("MTMPDIR");
501 #if defined(P_tmpdir)
502 if (directory == (char *) NULL)
503 directory=ConstantString(P_tmpdir);
505 if (directory == (char *) NULL)
507 value=GetPolicyValue("resource:temporary-path");
508 if (value != (char *) NULL)
510 (void) CloneString(&directory,value);
511 value=DestroyString(value);
513 if (strlen(directory) > (MagickPathExtent-25))
515 directory=DestroyString(directory);
518 status=GetPathAttributes(directory,&attributes);
519 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode))
521 directory=DestroyString(directory);
524 if (directory[strlen(directory)-1] == *DirectorySeparator)
525 (void) FormatLocaleString(path,MagickPathExtent,
526 "%smagick-%.20g" MagickPathTemplate,directory,(double) getpid());
528 (void) FormatLocaleString(path,MagickPathExtent,
529 "%s%smagick-%.20g" MagickPathTemplate,directory,DirectorySeparator,
531 directory=DestroyString(directory);
532 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
538 Ghostscript does not like backslashes so we need to replace them. The
539 forward slash also works under Windows.
541 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++)
542 if (*p == *DirectorySeparator)
549 MagickExport int AcquireUniqueFileResource(char *path)
551 #if !defined(O_NOFOLLOW)
554 #if !defined(TMP_MAX)
555 # define TMP_MAX 238328
569 portable_filename[65] =
570 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
578 assert(path != (char *) NULL);
579 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"...");
580 if (random_info == (RandomInfo *) NULL)
582 LockSemaphoreInfo(resource_semaphore);
583 if (random_info == (RandomInfo *) NULL)
584 random_info=AcquireRandomInfo();
585 UnlockSemaphoreInfo(resource_semaphore);
588 for (i=0; i < (ssize_t) TMP_MAX; i++)
594 Get temporary pathname.
596 (void) GetPathTemplate(path);
597 key=GetRandomKey(random_info,6);
598 p=path+strlen(path)-strlen(MagickPathTemplate);
599 datum=GetStringInfoDatum(key);
600 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
602 c=(int) (datum[j] & 0x3f);
603 *p++=portable_filename[c];
605 key=DestroyStringInfo(key);
606 #if defined(MAGICKCORE_HAVE_MKSTEMP)
610 #if defined(MAGICKCORE_HAVE_FCHMOD)
611 (void) fchmod(file,0600);
614 setmode(file,O_BINARY);
619 key=GetRandomKey(random_info,strlen(MagickPathTemplate));
620 p=path+strlen(path)-strlen(MagickPathTemplate);
621 datum=GetStringInfoDatum(key);
622 for (j=0; j < (ssize_t) GetStringInfoLength(key); j++)
624 c=(int) (datum[j] & 0x3f);
625 *p++=portable_filename[c];
627 key=DestroyStringInfo(key);
628 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW,
630 if ((file >= 0) || (errno != EEXIST))
633 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
636 if (resource_semaphore == (SemaphoreInfo *) NULL)
637 ActivateSemaphoreInfo(&resource_semaphore);
638 LockSemaphoreInfo(resource_semaphore);
639 if (temporary_resources == (SplayTreeInfo *) NULL)
640 temporary_resources=NewSplayTree(CompareSplayTreeString,
641 DestroyTemporaryResources,(void *(*)(void *)) NULL);
642 UnlockSemaphoreInfo(resource_semaphore);
643 (void) AddValueToSplayTree(temporary_resources,ConstantString(path),
644 (const void *) NULL);
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653 % G e t M a g i c k R e s o u r c e %
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 % GetMagickResource() returns the specified resource.
661 % The format of the GetMagickResource() method is:
663 % MagickSizeType GetMagickResource(const ResourceType type)
665 % A description of each parameter follows:
667 % o type: the type of resource.
670 MagickExport MagickSizeType GetMagickResource(const ResourceType type)
676 LockSemaphoreInfo(resource_semaphore);
681 resource=(MagickSizeType) resource_info.width;
686 resource=(MagickSizeType) resource_info.height;
691 resource=(MagickSizeType) resource_info.area;
696 resource=(MagickSizeType) resource_info.memory;
701 resource=(MagickSizeType) resource_info.map;
706 resource=(MagickSizeType) resource_info.disk;
711 resource=(MagickSizeType) resource_info.file;
716 resource=(MagickSizeType) resource_info.thread;
719 case ThrottleResource:
721 resource=(MagickSizeType) resource_info.throttle;
726 resource=(MagickSizeType) resource_info.time;
732 UnlockSemaphoreInfo(resource_semaphore);
737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
741 % G e t M a g i c k R e s o u r c e L i m i t %
745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
747 % GetMagickResourceLimit() returns the specified resource limit.
749 % The format of the GetMagickResourceLimit() method is:
751 % MagickSizeType GetMagickResourceLimit(const ResourceType type)
753 % A description of each parameter follows:
755 % o type: the type of resource.
758 MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type)
764 if (resource_semaphore == (SemaphoreInfo *) NULL)
765 ActivateSemaphoreInfo(&resource_semaphore);
766 LockSemaphoreInfo(resource_semaphore);
771 resource=resource_info.width_limit;
776 resource=resource_info.height_limit;
781 resource=resource_info.area_limit;
786 resource=resource_info.memory_limit;
791 resource=resource_info.map_limit;
796 resource=resource_info.disk_limit;
801 resource=resource_info.file_limit;
806 resource=resource_info.thread_limit;
809 case ThrottleResource:
811 resource=resource_info.throttle_limit;
816 resource=resource_info.time_limit;
822 UnlockSemaphoreInfo(resource_semaphore);
827 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 % L i s t M a g i c k R e s o u r c e I n f o %
835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 % ListMagickResourceInfo() lists the resource info to a file.
839 % The format of the ListMagickResourceInfo method is:
841 % MagickBooleanType ListMagickResourceInfo(FILE *file,
842 % ExceptionInfo *exception)
844 % A description of each parameter follows.
846 % o file: An pointer to a FILE.
848 % o exception: return any errors or warnings in this structure.
851 MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file,
852 ExceptionInfo *magick_unused(exception))
855 area_limit[MagickFormatExtent],
856 disk_limit[MagickFormatExtent],
857 height_limit[MagickFormatExtent],
858 map_limit[MagickFormatExtent],
859 memory_limit[MagickFormatExtent],
860 time_limit[MagickFormatExtent],
861 width_limit[MagickFormatExtent];
863 magick_unreferenced(exception);
865 if (file == (const FILE *) NULL)
867 if (resource_semaphore == (SemaphoreInfo *) NULL)
868 ActivateSemaphoreInfo(&resource_semaphore);
869 LockSemaphoreInfo(resource_semaphore);
870 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
871 MagickFormatExtent,width_limit);
872 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
873 MagickFormatExtent,height_limit);
874 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"P",
875 MagickFormatExtent,area_limit);
876 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
877 MagickFormatExtent,memory_limit);
878 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
879 MagickFormatExtent,map_limit);
880 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent);
881 if (resource_info.disk_limit != MagickResourceInfinity)
882 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
883 MagickFormatExtent,disk_limit);
884 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent);
885 if (resource_info.time_limit != MagickResourceInfinity)
886 (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double)
887 ((MagickOffsetType) resource_info.time_limit));
888 (void) FormatLocaleFile(file,"Resource limits:\n");
889 (void) FormatLocaleFile(file," Width: %s\n",width_limit);
890 (void) FormatLocaleFile(file," Height: %s\n",height_limit);
891 (void) FormatLocaleFile(file," Area: %s\n",area_limit);
892 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit);
893 (void) FormatLocaleFile(file," Map: %s\n",map_limit);
894 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit);
895 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType)
896 resource_info.file_limit));
897 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType)
898 resource_info.thread_limit));
899 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double)
900 ((MagickOffsetType) resource_info.throttle_limit));
901 (void) FormatLocaleFile(file," Time: %s\n",time_limit);
903 UnlockSemaphoreInfo(resource_semaphore);
908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912 % R e l i n q u i s h M a g i c k R e s o u r c e %
916 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
918 % RelinquishMagickResource() relinquishes resources of the specified type.
920 % The format of the RelinquishMagickResource() method is:
922 % void RelinquishMagickResource(const ResourceType type,
923 % const MagickSizeType size)
925 % A description of each parameter follows:
927 % o type: the type of resource.
929 % o size: the size of the resource.
932 MagickExport void RelinquishMagickResource(const ResourceType type,
933 const MagickSizeType size)
936 resource_current[MagickFormatExtent],
937 resource_limit[MagickFormatExtent],
938 resource_request[MagickFormatExtent];
943 logging=IsEventLogging();
944 if (resource_semaphore == (SemaphoreInfo *) NULL)
945 ActivateSemaphoreInfo(&resource_semaphore);
946 LockSemaphoreInfo(resource_semaphore);
951 resource_info.area=(MagickOffsetType) size;
952 if (logging != MagickFalse)
954 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
955 MagickFormatExtent,resource_request);
956 (void) FormatMagickSize((MagickSizeType) resource_info.area,
957 MagickFalse,(const char *) NULL,MagickFormatExtent,
959 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,
960 (const char *) NULL,MagickFormatExtent,resource_limit);
966 resource_info.memory-=size;
967 assert(resource_info.memory >= 0);
968 if (logging != MagickFalse)
970 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
972 (void) FormatMagickSize((MagickSizeType) resource_info.memory,
973 MagickTrue,"B",MagickFormatExtent,resource_current);
974 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B",
975 MagickFormatExtent,resource_limit);
981 resource_info.map-=size;
982 assert(resource_info.map >= 0);
983 if (logging != MagickFalse)
985 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
987 (void) FormatMagickSize((MagickSizeType) resource_info.map,
988 MagickTrue,"B",MagickFormatExtent,resource_current);
989 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B",
990 MagickFormatExtent,resource_limit);
996 resource_info.disk-=size;
997 assert(resource_info.disk >= 0);
998 if (logging != MagickFalse)
1000 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent,
1002 (void) FormatMagickSize((MagickSizeType) resource_info.disk,
1003 MagickTrue,"B",MagickFormatExtent,resource_current);
1004 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B",
1005 MagickFormatExtent,resource_limit);
1011 resource_info.file-=size;
1012 assert(resource_info.file >= 0);
1013 if (logging != MagickFalse)
1015 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
1016 MagickFormatExtent,resource_request);
1017 (void) FormatMagickSize((MagickSizeType) resource_info.file,
1018 MagickFalse,(const char *) NULL,MagickFormatExtent,
1020 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit,
1021 MagickFalse,(const char *) NULL,MagickFormatExtent,resource_limit);
1025 case HeightResource:
1027 resource_info.height=(MagickOffsetType) size;
1028 if (logging != MagickFalse)
1030 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
1032 (void) FormatMagickSize((MagickSizeType) resource_info.height,
1033 MagickFalse,"P",MagickFormatExtent,resource_current);
1034 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P",
1035 MagickFormatExtent,resource_limit);
1039 case ThreadResource:
1041 if (logging != MagickFalse)
1043 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
1044 MagickFormatExtent,resource_request);
1045 (void) FormatMagickSize((MagickSizeType) resource_info.thread,
1046 MagickFalse,(const char *) NULL,MagickFormatExtent,
1048 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit,
1049 MagickFalse,(const char *) NULL,MagickFormatExtent,resource_limit);
1053 case ThrottleResource:
1055 if (logging != MagickFalse)
1057 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
1058 MagickFormatExtent,resource_request);
1059 (void) FormatMagickSize((MagickSizeType) resource_info.throttle,
1060 MagickFalse,(const char *) NULL,MagickFormatExtent,
1062 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit,
1063 MagickFalse,(const char *) NULL,MagickFormatExtent,resource_limit);
1069 resource_info.time-=size;
1070 assert(resource_info.time >= 0);
1071 if (logging != MagickFalse)
1073 (void) FormatMagickSize(size,MagickFalse,(const char *) NULL,
1074 MagickFormatExtent,resource_request);
1075 (void) FormatMagickSize((MagickSizeType) resource_info.time,
1076 MagickFalse,(const char *) NULL,MagickFormatExtent,
1078 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit,
1079 MagickFalse,(const char *) NULL,MagickFormatExtent,resource_limit);
1085 resource_info.width=(MagickOffsetType) size;
1086 if (logging != MagickFalse)
1088 (void) FormatMagickSize(size,MagickFalse,"P",MagickFormatExtent,
1090 (void) FormatMagickSize((MagickSizeType) resource_info.width,
1091 MagickFalse,"P",MagickFormatExtent,resource_current);
1092 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P",
1093 MagickFormatExtent,resource_limit);
1100 UnlockSemaphoreInfo(resource_semaphore);
1101 if (logging != MagickFalse)
1103 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s",
1104 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type),
1105 resource_request,resource_current,resource_limit);
1110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1114 % 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 %
1118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1120 % RelinquishUniqueFileResource() relinquishes a unique file resource.
1122 % The format of the RelinquishUniqueFileResource() method is:
1124 % MagickBooleanType RelinquishUniqueFileResource(const char *path)
1126 % A description of each parameter follows:
1128 % o name: the name of the temporary resource.
1131 MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path)
1134 cache_path[MagickPathExtent];
1139 assert(path != (const char *) NULL);
1141 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path);
1142 if (resource_semaphore == (SemaphoreInfo *) NULL)
1143 ActivateSemaphoreInfo(&resource_semaphore);
1144 LockSemaphoreInfo(resource_semaphore);
1145 if (temporary_resources != (SplayTreeInfo *) NULL)
1146 status=DeleteNodeFromSplayTree(temporary_resources,(const void *) path);
1147 UnlockSemaphoreInfo(resource_semaphore);
1148 (void) CopyMagickString(cache_path,path,MagickPathExtent);
1149 AppendImageFormat("cache",cache_path);
1150 (void) ShredFile(cache_path);
1151 if (status == MagickFalse)
1152 status=ShredFile(path);
1157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1161 + R e s o u r c e C o m p o n e n t G e n e s i s %
1165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1167 % ResourceComponentGenesis() instantiates the resource component.
1169 % The format of the ResourceComponentGenesis method is:
1171 % MagickBooleanType ResourceComponentGenesis(void)
1175 static inline MagickSizeType StringToSizeType(const char *string,
1176 const double interval)
1181 value=SiPrefixToDoubleInterval(string,interval);
1182 if (value >= (double) MagickULLConstant(~0))
1183 return(MagickULLConstant(~0));
1184 return((MagickSizeType) value);
1187 MagickPrivate MagickBooleanType ResourceComponentGenesis(void)
1201 Set Magick resource limits.
1203 if (resource_semaphore == (SemaphoreInfo *) NULL)
1204 resource_semaphore=AcquireSemaphoreInfo();
1205 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit);
1206 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT");
1207 if (limit != (char *) NULL)
1209 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit,
1211 limit=DestroyString(limit);
1213 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit);
1214 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT");
1215 if (limit != (char *) NULL)
1217 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit,
1219 limit=DestroyString(limit);
1221 pagesize=GetMagickPageSize();
1223 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES)
1224 pages=(ssize_t) sysconf(_SC_PHYS_PAGES);
1226 memory=(MagickSizeType) pages*pagesize;
1227 if ((pagesize <= 0) || (pages <= 0))
1228 memory=2048UL*1024UL*1024UL;
1229 #if defined(PixelCacheThreshold)
1230 memory=PixelCacheThreshold;
1232 (void) SetMagickResourceLimit(AreaResource,2*memory);
1233 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT");
1234 if (limit != (char *) NULL)
1236 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0));
1237 limit=DestroyString(limit);
1239 (void) SetMagickResourceLimit(MemoryResource,memory);
1240 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT");
1241 if (limit != (char *) NULL)
1243 (void) SetMagickResourceLimit(MemoryResource,
1244 StringToSizeType(limit,100.0));
1245 limit=DestroyString(limit);
1247 (void) SetMagickResourceLimit(MapResource,2*memory);
1248 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT");
1249 if (limit != (char *) NULL)
1251 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0));
1252 limit=DestroyString(limit);
1254 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity);
1255 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT");
1256 if (limit != (char *) NULL)
1258 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0));
1259 limit=DestroyString(limit);
1262 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
1263 files=(ssize_t) sysconf(_SC_OPEN_MAX);
1265 #if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
1271 if (getrlimit(RLIMIT_NOFILE,&resources) != -1)
1272 files=(ssize_t) resources.rlim_cur;
1275 #if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
1277 files=(ssize_t) getdtablesize();
1281 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t)
1283 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT");
1284 if (limit != (char *) NULL)
1286 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit,
1288 limit=DestroyString(limit);
1290 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads());
1291 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT");
1292 if (limit != (char *) NULL)
1294 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit,
1296 limit=DestroyString(limit);
1298 (void) SetMagickResourceLimit(ThrottleResource,0);
1299 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT");
1300 if (limit != (char *) NULL)
1302 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit,
1304 limit=DestroyString(limit);
1306 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity);
1307 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT");
1308 if (limit != (char *) NULL)
1310 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0));
1311 limit=DestroyString(limit);
1317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1321 + 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 %
1325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1327 % ResourceComponentTerminus() destroys the resource component.
1329 % The format of the ResourceComponentTerminus() method is:
1331 % ResourceComponentTerminus(void)
1334 MagickPrivate void ResourceComponentTerminus(void)
1336 if (resource_semaphore == (SemaphoreInfo *) NULL)
1337 resource_semaphore=AcquireSemaphoreInfo();
1338 LockSemaphoreInfo(resource_semaphore);
1339 if (temporary_resources != (SplayTreeInfo *) NULL)
1340 temporary_resources=DestroySplayTree(temporary_resources);
1341 if (random_info != (RandomInfo *) NULL)
1342 random_info=DestroyRandomInfo(random_info);
1343 UnlockSemaphoreInfo(resource_semaphore);
1344 RelinquishSemaphoreInfo(&resource_semaphore);
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1352 % S e t M a g i c k R e s o u r c e L i m i t %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1358 % SetMagickResourceLimit() sets the limit for a particular resource.
1360 % The format of the SetMagickResourceLimit() method is:
1362 % MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1363 % const MagickSizeType limit)
1365 % A description of each parameter follows:
1367 % o type: the type of resource.
1369 % o limit: the maximum limit for the resource.
1373 MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type,
1374 const MagickSizeType limit)
1379 if (resource_semaphore == (SemaphoreInfo *) NULL)
1380 resource_semaphore=AcquireSemaphoreInfo();
1381 LockSemaphoreInfo(resource_semaphore);
1382 value=(char *) NULL;
1387 resource_info.width_limit=limit;
1388 value=GetPolicyValue("resource:width");
1389 if (value != (char *) NULL)
1390 resource_info.width_limit=MagickMin(limit,StringToSizeType(value,
1394 case HeightResource:
1396 resource_info.height_limit=limit;
1397 value=GetPolicyValue("resource:height");
1398 if (value != (char *) NULL)
1399 resource_info.height_limit=MagickMin(limit,StringToSizeType(value,
1405 resource_info.area_limit=limit;
1406 value=GetPolicyValue("resource:area");
1407 if (value != (char *) NULL)
1408 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0));
1411 case MemoryResource:
1413 resource_info.memory_limit=limit;
1414 value=GetPolicyValue("resource:memory");
1415 if (value != (char *) NULL)
1416 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value,
1422 resource_info.map_limit=limit;
1423 value=GetPolicyValue("resource:map");
1424 if (value != (char *) NULL)
1425 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0));
1430 resource_info.disk_limit=limit;
1431 value=GetPolicyValue("resource:disk");
1432 if (value != (char *) NULL)
1433 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0));
1438 resource_info.file_limit=limit;
1439 value=GetPolicyValue("resource:file");
1440 if (value != (char *) NULL)
1441 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0));
1444 case ThreadResource:
1446 resource_info.thread_limit=limit;
1447 value=GetPolicyValue("resource:thread");
1448 if (value != (char *) NULL)
1449 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value,
1451 if (resource_info.thread_limit > GetOpenMPMaximumThreads())
1452 resource_info.thread_limit=GetOpenMPMaximumThreads();
1454 if (resource_info.thread_limit == 0)
1455 resource_info.thread_limit=1;
1458 case ThrottleResource:
1460 resource_info.throttle_limit=limit;
1461 value=GetPolicyValue("resource:throttle");
1462 if (value != (char *) NULL)
1463 resource_info.throttle_limit=MagickMax(limit,StringToSizeType(value,
1469 resource_info.time_limit=limit;
1470 value=GetPolicyValue("resource:time");
1471 if (value != (char *) NULL)
1472 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0));
1473 ResetPixelCacheEpoch();
1479 if (value != (char *) NULL)
1480 value=DestroyString(value);
1481 UnlockSemaphoreInfo(resource_semaphore);