1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 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 % 11% % 12% % 13% Get/Set MagickCore Resources % 14% % 15% Software Design % 16% Cristy % 17% September 2002 % 18% % 19% % 20% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21% dedicated to making software imaging solutions freely available. % 22% % 23% You may not use this file except in compliance with the License. You may % 24% obtain a copy of the License at % 25% % 26% http://www.imagemagick.org/script/license.php % 27% % 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. % 33% % 34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35% 36% 37*/ 38 39/* 40 Include declarations. 41*/ 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" 69 70/* 71 Typedef declarations. 72*/ 73typedef struct _ResourceInfo 74{ 75 MagickOffsetType 76 width, 77 height, 78 area, 79 memory, 80 map, 81 disk, 82 file, 83 thread, 84 throttle, 85 time; 86 87 MagickSizeType 88 width_limit, 89 height_limit, 90 area_limit, 91 memory_limit, 92 map_limit, 93 disk_limit, 94 file_limit, 95 thread_limit, 96 throttle_limit, 97 time_limit; 98} ResourceInfo; 99 100/* 101 Global declarations. 102*/ 103static RandomInfo 104 *random_info = (RandomInfo *) NULL; 105 106static ResourceInfo 107 resource_info = 108 { 109 MagickULLConstant(0), /* initial width */ 110 MagickULLConstant(0), /* initial height */ 111 MagickULLConstant(0), /* initial area */ 112 MagickULLConstant(0), /* initial memory */ 113 MagickULLConstant(0), /* initial map */ 114 MagickULLConstant(0), /* initial disk */ 115 MagickULLConstant(0), /* initial file */ 116 MagickULLConstant(0), /* initial thread */ 117 MagickULLConstant(0), /* initial throttle */ 118 MagickULLConstant(0), /* initial time */ 119 (INT_MAX/(5*sizeof(Quantum))), /* width limit */ 120 (INT_MAX/(5*sizeof(Quantum))), /* height limit */ 121 MagickULLConstant(3072)*1024*1024, /* area limit */ 122 MagickULLConstant(1536)*1024*1024, /* memory limit */ 123 MagickULLConstant(3072)*1024*1024, /* map limit */ 124 MagickResourceInfinity, /* disk limit */ 125 MagickULLConstant(768), /* file limit */ 126 MagickULLConstant(1), /* thread limit */ 127 MagickULLConstant(0), /* throttle limit */ 128 MagickResourceInfinity /* time limit */ 129 }; 130 131static SemaphoreInfo 132 *resource_semaphore = (SemaphoreInfo *) NULL; 133 134static SplayTreeInfo 135 *temporary_resources = (SplayTreeInfo *) NULL; 136 137/* 138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 139% % 140% % 141% % 142% A c q u i r e M a g i c k R e s o u r c e % 143% % 144% % 145% % 146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 147% 148% AcquireMagickResource() acquires resources of the specified type. 149% MagickFalse is returned if the specified resource is exhausted otherwise 150% MagickTrue. 151% 152% The format of the AcquireMagickResource() method is: 153% 154% MagickBooleanType AcquireMagickResource(const ResourceType type, 155% const MagickSizeType size) 156% 157% A description of each parameter follows: 158% 159% o type: the type of resource. 160% 161% o size: the number of bytes needed from for this resource. 162% 163*/ 164MagickExport MagickBooleanType AcquireMagickResource(const ResourceType type, 165 const MagickSizeType size) 166{ 167 char 168 resource_current[MagickFormatExtent], 169 resource_limit[MagickFormatExtent], 170 resource_request[MagickFormatExtent]; 171 172 MagickBooleanType 173 status; 174 175 MagickSizeType 176 limit; 177 178 status=MagickFalse; 179 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent, 180 resource_request); 181 if (resource_semaphore == (SemaphoreInfo *) NULL) 182 ActivateSemaphoreInfo(&resource_semaphore); 183 LockSemaphoreInfo(resource_semaphore); 184 switch (type) 185 { 186 case AreaResource: 187 { 188 resource_info.area=(MagickOffsetType) size; 189 limit=resource_info.area_limit; 190 status=(resource_info.area_limit == MagickResourceInfinity) || 191 (size < limit) ? MagickTrue : MagickFalse; 192 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse, 193 "B",MagickFormatExtent,resource_current); 194 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B", 195 MagickFormatExtent,resource_limit); 196 break; 197 } 198 case MemoryResource: 199 { 200 resource_info.memory+=size; 201 limit=resource_info.memory_limit; 202 status=(resource_info.memory_limit == MagickResourceInfinity) || 203 ((MagickSizeType) resource_info.memory < limit) ? MagickTrue : 204 MagickFalse; 205 (void) FormatMagickSize((MagickSizeType) resource_info.memory,MagickTrue, 206 "B",MagickFormatExtent,resource_current); 207 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B", 208 MagickFormatExtent,resource_limit); 209 break; 210 } 211 case MapResource: 212 { 213 resource_info.map+=size; 214 limit=resource_info.map_limit; 215 status=(resource_info.map_limit == MagickResourceInfinity) || 216 ((MagickSizeType) resource_info.map < limit) ? MagickTrue : MagickFalse; 217 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue, 218 "B",MagickFormatExtent,resource_current); 219 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B", 220 MagickFormatExtent,resource_limit); 221 break; 222 } 223 case DiskResource: 224 { 225 resource_info.disk+=size; 226 limit=resource_info.disk_limit; 227 status=(resource_info.disk_limit == MagickResourceInfinity) || 228 ((MagickSizeType) resource_info.disk < limit) ? MagickTrue : 229 MagickFalse; 230 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue, 231 "B",MagickFormatExtent,resource_current); 232 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B", 233 MagickFormatExtent,resource_limit); 234 break; 235 } 236 case FileResource: 237 { 238 resource_info.file+=size; 239 limit=resource_info.file_limit; 240 status=(resource_info.file_limit == MagickResourceInfinity) || 241 ((MagickSizeType) resource_info.file < limit) ? 242 MagickTrue : MagickFalse; 243 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse, 244 "B",MagickFormatExtent,resource_current); 245 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit, 246 MagickFalse,"B",MagickFormatExtent,resource_limit); 247 break; 248 } 249 case HeightResource: 250 { 251 resource_info.area=(MagickOffsetType) size; 252 limit=resource_info.height_limit; 253 status=(resource_info.area_limit == MagickResourceInfinity) || 254 (size < limit) ? MagickTrue : MagickFalse; 255 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse, 256 "P",MagickFormatExtent,resource_current); 257 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P", 258 MagickFormatExtent,resource_limit); 259 break; 260 } 261 case ThreadResource: 262 { 263 limit=resource_info.thread_limit; 264 status=(resource_info.thread_limit == MagickResourceInfinity) || 265 ((MagickSizeType) resource_info.thread < limit) ? 266 MagickTrue : MagickFalse; 267 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse, 268 "B",MagickFormatExtent,resource_current); 269 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit, 270 MagickFalse,"B",MagickFormatExtent,resource_limit); 271 break; 272 } 273 case ThrottleResource: 274 { 275 limit=resource_info.throttle_limit; 276 status=(resource_info.throttle_limit == MagickResourceInfinity) || 277 ((MagickSizeType) resource_info.throttle < limit) ? 278 MagickTrue : MagickFalse; 279 (void) FormatMagickSize((MagickSizeType) resource_info.throttle, 280 MagickFalse,"B",MagickFormatExtent,resource_current); 281 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit, 282 MagickFalse,"B",MagickFormatExtent,resource_limit); 283 break; 284 } 285 case TimeResource: 286 { 287 resource_info.time+=size; 288 limit=resource_info.time_limit; 289 status=(resource_info.time_limit == MagickResourceInfinity) || 290 ((MagickSizeType) resource_info.time < limit) ? 291 MagickTrue : MagickFalse; 292 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse, 293 "B",MagickFormatExtent,resource_current); 294 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit, 295 MagickFalse,"B",MagickFormatExtent,resource_limit); 296 break; 297 } 298 case WidthResource: 299 { 300 resource_info.area=(MagickOffsetType) size; 301 limit=resource_info.width_limit; 302 status=(resource_info.area_limit == MagickResourceInfinity) || 303 (size < limit) ? MagickTrue : MagickFalse; 304 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse, 305 "P",MagickFormatExtent,resource_current); 306 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P", 307 MagickFormatExtent,resource_limit); 308 break; 309 } 310 default: 311 break; 312 } 313 UnlockSemaphoreInfo(resource_semaphore); 314 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s", 315 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type), 316 resource_request,resource_current,resource_limit); 317 return(status); 318} 319 320/* 321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 322% % 323% % 324% % 325+ A s y n c h r o n o u s R e s o u r c e C o m p o n e n t T e r m i n u s % 326% % 327% % 328% % 329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 330% 331% AsynchronousResourceComponentTerminus() destroys the resource environment. 332% It differs from ResourceComponentTerminus() in that it can be called from a 333% asynchronous signal handler. 334% 335% The format of the ResourceComponentTerminus() method is: 336% 337% ResourceComponentTerminus(void) 338% 339*/ 340MagickPrivate void AsynchronousResourceComponentTerminus(void) 341{ 342 const char 343 *path; 344 345 if (temporary_resources == (SplayTreeInfo *) NULL) 346 return; 347 /* 348 Remove any lingering temporary files. 349 */ 350 ResetSplayTreeIterator(temporary_resources); 351 path=(const char *) GetNextKeyInSplayTree(temporary_resources); 352 while (path != (const char *) NULL) 353 { 354 (void) ShredFile(path); 355 path=(const char *) GetNextKeyInSplayTree(temporary_resources); 356 } 357} 358 359/* 360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 361% % 362% % 363% % 364% A c q u i r e U n i q u e F i l e R e s o u r c e % 365% % 366% % 367% % 368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 369% 370% AcquireUniqueFileResource() returns a unique file name, and returns a file 371% descriptor for the file open for reading and writing. 372% 373% The format of the AcquireUniqueFileResource() method is: 374% 375% int AcquireUniqueFileResource(char *path) 376% 377% A description of each parameter follows: 378% 379% o path: Specifies a pointer to an array of characters. The unique path 380% name is returned in this array. 381% 382*/ 383 384static void *DestroyTemporaryResources(void *temporary_resource) 385{ 386 (void) ShredFile((char *) temporary_resource); 387 temporary_resource=DestroyString((char *) temporary_resource); 388 return((void *) NULL); 389} 390 391MagickExport MagickBooleanType GetPathTemplate(char *path) 392{ 393 char 394 *directory, 395 *value; 396 397 ExceptionInfo 398 *exception; 399 400 MagickBooleanType 401 status; 402 403 struct stat 404 attributes; 405 406 (void) FormatLocaleString(path,MagickPathExtent,"magick-%.20gXXXXXXXXXXXX", 407 (double) getpid()); 408 exception=AcquireExceptionInfo(); 409 directory=(char *) GetImageRegistry(StringRegistryType,"temporary-path", 410 exception); 411 exception=DestroyExceptionInfo(exception); 412 if (directory == (char *) NULL) 413 directory=GetEnvironmentValue("MAGICK_TEMPORARY_PATH"); 414 if (directory == (char *) NULL) 415 directory=GetEnvironmentValue("MAGICK_TMPDIR"); 416 if (directory == (char *) NULL) 417 directory=GetEnvironmentValue("TMPDIR"); 418#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__OS2__) || defined(__CYGWIN__) 419 if (directory == (char *) NULL) 420 directory=GetEnvironmentValue("TMP"); 421 if (directory == (char *) NULL) 422 directory=GetEnvironmentValue("TEMP"); 423#endif 424#if defined(__VMS) 425 if (directory == (char *) NULL) 426 directory=GetEnvironmentValue("MTMPDIR"); 427#endif 428#if defined(P_tmpdir) 429 if (directory == (char *) NULL) 430 directory=ConstantString(P_tmpdir); 431#endif 432 if (directory == (char *) NULL) 433 return(MagickTrue); 434 value=GetPolicyValue("temporary-path"); 435 if (value != (char *) NULL) 436 (void) CloneString(&directory,value); 437 if (strlen(directory) > (MagickPathExtent-25)) 438 { 439 directory=DestroyString(directory); 440 return(MagickFalse); 441 } 442 status=GetPathAttributes(directory,&attributes); 443 if ((status == MagickFalse) || !S_ISDIR(attributes.st_mode)) 444 { 445 directory=DestroyString(directory); 446 return(MagickFalse); 447 } 448 if (directory[strlen(directory)-1] == *DirectorySeparator) 449 (void) FormatLocaleString(path,MagickPathExtent, 450 "%smagick-%.20gXXXXXXXXXXXX",directory,(double) getpid()); 451 else 452 (void) FormatLocaleString(path,MagickPathExtent, 453 "%s%smagick-%.20gXXXXXXXXXXXX",directory,DirectorySeparator,(double) 454 getpid()); 455 directory=DestroyString(directory); 456#if defined(MAGICKCORE_WINDOWS_SUPPORT) 457 { 458 register char 459 *p; 460 461 /* 462 Ghostscript does not like backslashes so we need to replace them. The 463 forward slash also works under Windows. 464 */ 465 for (p=(path[1] == *DirectorySeparator ? path+2 : path); *p != '\0'; p++) 466 if (*p == *DirectorySeparator) 467 *p='/'; 468 } 469#endif 470 return(MagickTrue); 471} 472 473MagickExport int AcquireUniqueFileResource(char *path) 474{ 475#if !defined(O_NOFOLLOW) 476#define O_NOFOLLOW 0 477#endif 478#if !defined(TMP_MAX) 479# define TMP_MAX 238328 480#endif 481 482 int 483 c, 484 file; 485 486 register char 487 *p; 488 489 register ssize_t 490 i; 491 492 static const char 493 portable_filename[65] = 494 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"; 495 496 StringInfo 497 *key; 498 499 unsigned char 500 *datum; 501 502 assert(path != (char *) NULL); 503 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"..."); 504 if (random_info == (RandomInfo *) NULL) 505 { 506 LockSemaphoreInfo(resource_semaphore); 507 if (random_info == (RandomInfo *) NULL) 508 random_info=AcquireRandomInfo(); 509 UnlockSemaphoreInfo(resource_semaphore); 510 } 511 file=(-1); 512 for (i=0; i < (ssize_t) TMP_MAX; i++) 513 { 514 /* 515 Get temporary pathname. 516 */ 517 (void) GetPathTemplate(path); 518 key=GetRandomKey(random_info,6); 519 p=path+strlen(path)-12; 520 datum=GetStringInfoDatum(key); 521 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++) 522 { 523 c=(int) (datum[i] & 0x3f); 524 *p++=portable_filename[c]; 525 } 526 key=DestroyStringInfo(key); 527#if defined(MAGICKCORE_HAVE_MKSTEMP) 528 file=mkstemp(path); 529 if (file != -1) 530 { 531#if defined(MAGICKCORE_HAVE_FCHMOD) 532 (void) fchmod(file,0600); 533#endif 534#if defined(__OS2__) 535 setmode(file,O_BINARY); 536#endif 537 break; 538 } 539#endif 540 key=GetRandomKey(random_info,12); 541 p=path+strlen(path)-12; 542 datum=GetStringInfoDatum(key); 543 for (i=0; i < (ssize_t) GetStringInfoLength(key); i++) 544 { 545 c=(int) (datum[i] & 0x3f); 546 *p++=portable_filename[c]; 547 } 548 key=DestroyStringInfo(key); 549 file=open_utf8(path,O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_NOFOLLOW, 550 S_MODE); 551 if ((file >= 0) || (errno != EEXIST)) 552 break; 553 } 554 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); 555 if (file == -1) 556 return(file); 557 if (resource_semaphore == (SemaphoreInfo *) NULL) 558 ActivateSemaphoreInfo(&resource_semaphore); 559 LockSemaphoreInfo(resource_semaphore); 560 if (temporary_resources == (SplayTreeInfo *) NULL) 561 temporary_resources=NewSplayTree(CompareSplayTreeString, 562 DestroyTemporaryResources,(void *(*)(void *)) NULL); 563 UnlockSemaphoreInfo(resource_semaphore); 564 (void) AddValueToSplayTree(temporary_resources,ConstantString(path), 565 (const void *) NULL); 566 return(file); 567} 568 569/* 570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 571% % 572% % 573% % 574% G e t M a g i c k R e s o u r c e % 575% % 576% % 577% % 578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 579% 580% GetMagickResource() returns the specified resource. 581% 582% The format of the GetMagickResource() method is: 583% 584% MagickSizeType GetMagickResource(const ResourceType type) 585% 586% A description of each parameter follows: 587% 588% o type: the type of resource. 589% 590*/ 591MagickExport MagickSizeType GetMagickResource(const ResourceType type) 592{ 593 MagickSizeType 594 resource; 595 596 resource=0; 597 LockSemaphoreInfo(resource_semaphore); 598 switch (type) 599 { 600 case WidthResource: 601 { 602 resource=(MagickSizeType) resource_info.width; 603 break; 604 } 605 case HeightResource: 606 { 607 resource=(MagickSizeType) resource_info.height; 608 break; 609 } 610 case AreaResource: 611 { 612 resource=(MagickSizeType) resource_info.area; 613 break; 614 } 615 case MemoryResource: 616 { 617 resource=(MagickSizeType) resource_info.memory; 618 break; 619 } 620 case MapResource: 621 { 622 resource=(MagickSizeType) resource_info.map; 623 break; 624 } 625 case DiskResource: 626 { 627 resource=(MagickSizeType) resource_info.disk; 628 break; 629 } 630 case FileResource: 631 { 632 resource=(MagickSizeType) resource_info.file; 633 break; 634 } 635 case ThreadResource: 636 { 637 resource=(MagickSizeType) resource_info.thread; 638 break; 639 } 640 case ThrottleResource: 641 { 642 resource=(MagickSizeType) resource_info.throttle; 643 break; 644 } 645 case TimeResource: 646 { 647 resource=(MagickSizeType) resource_info.time; 648 break; 649 } 650 default: 651 break; 652 } 653 UnlockSemaphoreInfo(resource_semaphore); 654 return(resource); 655} 656 657/* 658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 659% % 660% % 661% % 662% G e t M a g i c k R e s o u r c e L i m i t % 663% % 664% % 665% % 666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 667% 668% GetMagickResourceLimit() returns the specified resource limit. 669% 670% The format of the GetMagickResourceLimit() method is: 671% 672% MagickSizeType GetMagickResourceLimit(const ResourceType type) 673% 674% A description of each parameter follows: 675% 676% o type: the type of resource. 677% 678*/ 679MagickExport MagickSizeType GetMagickResourceLimit(const ResourceType type) 680{ 681 MagickSizeType 682 resource; 683 684 resource=0; 685 if (resource_semaphore == (SemaphoreInfo *) NULL) 686 ActivateSemaphoreInfo(&resource_semaphore); 687 LockSemaphoreInfo(resource_semaphore); 688 switch (type) 689 { 690 case WidthResource: 691 { 692 resource=resource_info.width_limit; 693 break; 694 } 695 case HeightResource: 696 { 697 resource=resource_info.height_limit; 698 break; 699 } 700 case AreaResource: 701 { 702 resource=resource_info.area_limit; 703 break; 704 } 705 case MemoryResource: 706 { 707 resource=resource_info.memory_limit; 708 break; 709 } 710 case MapResource: 711 { 712 resource=resource_info.map_limit; 713 break; 714 } 715 case DiskResource: 716 { 717 resource=resource_info.disk_limit; 718 break; 719 } 720 case FileResource: 721 { 722 resource=resource_info.file_limit; 723 break; 724 } 725 case ThreadResource: 726 { 727 resource=resource_info.thread_limit; 728 break; 729 } 730 case ThrottleResource: 731 { 732 resource=resource_info.throttle_limit; 733 break; 734 } 735 case TimeResource: 736 { 737 resource=resource_info.time_limit; 738 break; 739 } 740 default: 741 break; 742 } 743 UnlockSemaphoreInfo(resource_semaphore); 744 return(resource); 745} 746 747/* 748%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 749% % 750% % 751% % 752% L i s t M a g i c k R e s o u r c e I n f o % 753% % 754% % 755% % 756%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 757% 758% ListMagickResourceInfo() lists the resource info to a file. 759% 760% The format of the ListMagickResourceInfo method is: 761% 762% MagickBooleanType ListMagickResourceInfo(FILE *file, 763% ExceptionInfo *exception) 764% 765% A description of each parameter follows. 766% 767% o file: An pointer to a FILE. 768% 769% o exception: return any errors or warnings in this structure. 770% 771*/ 772MagickExport MagickBooleanType ListMagickResourceInfo(FILE *file, 773 ExceptionInfo *magick_unused(exception)) 774{ 775 char 776 area_limit[MagickFormatExtent], 777 disk_limit[MagickFormatExtent], 778 height_limit[MagickFormatExtent], 779 map_limit[MagickFormatExtent], 780 memory_limit[MagickFormatExtent], 781 time_limit[MagickFormatExtent], 782 width_limit[MagickFormatExtent]; 783 784 magick_unreferenced(exception); 785 786 if (file == (const FILE *) NULL) 787 file=stdout; 788 if (resource_semaphore == (SemaphoreInfo *) NULL) 789 ActivateSemaphoreInfo(&resource_semaphore); 790 LockSemaphoreInfo(resource_semaphore); 791 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P", 792 MagickFormatExtent,width_limit); 793 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P", 794 MagickFormatExtent,height_limit); 795 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B", 796 MagickFormatExtent,area_limit); 797 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B", 798 MagickFormatExtent,memory_limit); 799 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B", 800 MagickFormatExtent,map_limit); 801 (void) CopyMagickString(disk_limit,"unlimited",MagickFormatExtent); 802 if (resource_info.disk_limit != MagickResourceInfinity) 803 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B", 804 MagickFormatExtent,disk_limit); 805 (void) CopyMagickString(time_limit,"unlimited",MagickFormatExtent); 806 if (resource_info.time_limit != MagickResourceInfinity) 807 (void) FormatLocaleString(time_limit,MagickFormatExtent,"%.20g",(double) 808 ((MagickOffsetType) resource_info.time_limit)); 809 (void) FormatLocaleFile(file,"Resource limits:\n"); 810 (void) FormatLocaleFile(file," Width: %s\n",width_limit); 811 (void) FormatLocaleFile(file," Height: %s\n",height_limit); 812 (void) FormatLocaleFile(file," Area: %s\n",area_limit); 813 (void) FormatLocaleFile(file," Memory: %s\n",memory_limit); 814 (void) FormatLocaleFile(file," Map: %s\n",map_limit); 815 (void) FormatLocaleFile(file," Disk: %s\n",disk_limit); 816 (void) FormatLocaleFile(file," File: %.20g\n",(double) ((MagickOffsetType) 817 resource_info.file_limit)); 818 (void) FormatLocaleFile(file," Thread: %.20g\n",(double) ((MagickOffsetType) 819 resource_info.thread_limit)); 820 (void) FormatLocaleFile(file," Throttle: %.20g\n",(double) 821 ((MagickOffsetType) resource_info.throttle_limit)); 822 (void) FormatLocaleFile(file," Time: %s\n",time_limit); 823 (void) fflush(file); 824 UnlockSemaphoreInfo(resource_semaphore); 825 return(MagickTrue); 826} 827 828/* 829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 830% % 831% % 832% % 833% R e l i n q u i s h M a g i c k R e s o u r c e % 834% % 835% % 836% % 837%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 838% 839% RelinquishMagickResource() relinquishes resources of the specified type. 840% 841% The format of the RelinquishMagickResource() method is: 842% 843% void RelinquishMagickResource(const ResourceType type, 844% const MagickSizeType size) 845% 846% A description of each parameter follows: 847% 848% o type: the type of resource. 849% 850% o size: the size of the resource. 851% 852*/ 853MagickExport void RelinquishMagickResource(const ResourceType type, 854 const MagickSizeType size) 855{ 856 char 857 resource_current[MagickFormatExtent], 858 resource_limit[MagickFormatExtent], 859 resource_request[MagickFormatExtent]; 860 861 (void) FormatMagickSize(size,MagickFalse,"B",MagickFormatExtent, 862 resource_request); 863 if (resource_semaphore == (SemaphoreInfo *) NULL) 864 ActivateSemaphoreInfo(&resource_semaphore); 865 LockSemaphoreInfo(resource_semaphore); 866 switch (type) 867 { 868 case WidthResource: 869 { 870 resource_info.width=(MagickOffsetType) size; 871 (void) FormatMagickSize((MagickSizeType) resource_info.width,MagickFalse, 872 "P",MagickFormatExtent,resource_current); 873 (void) FormatMagickSize(resource_info.width_limit,MagickFalse,"P", 874 MagickFormatExtent,resource_limit); 875 break; 876 } 877 case HeightResource: 878 { 879 resource_info.height=(MagickOffsetType) size; 880 (void) FormatMagickSize((MagickSizeType) resource_info.height,MagickFalse, 881 "P",MagickFormatExtent,resource_current); 882 (void) FormatMagickSize(resource_info.height_limit,MagickFalse,"P", 883 MagickFormatExtent,resource_limit); 884 break; 885 } 886 case AreaResource: 887 { 888 resource_info.area=(MagickOffsetType) size; 889 (void) FormatMagickSize((MagickSizeType) resource_info.area,MagickFalse, 890 "B",MagickFormatExtent,resource_current); 891 (void) FormatMagickSize(resource_info.area_limit,MagickFalse,"B", 892 MagickFormatExtent,resource_limit); 893 break; 894 } 895 case MemoryResource: 896 { 897 resource_info.memory-=size; 898 (void) FormatMagickSize((MagickSizeType) resource_info.memory, 899 MagickTrue,"B",MagickFormatExtent,resource_current); 900 (void) FormatMagickSize(resource_info.memory_limit,MagickTrue,"B", 901 MagickFormatExtent,resource_limit); 902 break; 903 } 904 case MapResource: 905 { 906 resource_info.map-=size; 907 (void) FormatMagickSize((MagickSizeType) resource_info.map,MagickTrue, 908 "B",MagickFormatExtent,resource_current); 909 (void) FormatMagickSize(resource_info.map_limit,MagickTrue,"B", 910 MagickFormatExtent,resource_limit); 911 break; 912 } 913 case DiskResource: 914 { 915 resource_info.disk-=size; 916 (void) FormatMagickSize((MagickSizeType) resource_info.disk,MagickTrue, 917 "B",MagickFormatExtent,resource_current); 918 (void) FormatMagickSize(resource_info.disk_limit,MagickTrue,"B", 919 MagickFormatExtent,resource_limit); 920 break; 921 } 922 case FileResource: 923 { 924 resource_info.file-=size; 925 (void) FormatMagickSize((MagickSizeType) resource_info.file,MagickFalse, 926 "B",MagickFormatExtent,resource_current); 927 (void) FormatMagickSize((MagickSizeType) resource_info.file_limit, 928 MagickFalse,"B",MagickFormatExtent,resource_limit); 929 break; 930 } 931 case ThreadResource: 932 { 933 (void) FormatMagickSize((MagickSizeType) resource_info.thread,MagickFalse, 934 "B",MagickFormatExtent,resource_current); 935 (void) FormatMagickSize((MagickSizeType) resource_info.thread_limit, 936 MagickFalse,"B",MagickFormatExtent,resource_limit); 937 break; 938 } 939 case ThrottleResource: 940 { 941 (void) FormatMagickSize((MagickSizeType) resource_info.throttle, 942 MagickFalse,"B",MagickFormatExtent,resource_current); 943 (void) FormatMagickSize((MagickSizeType) resource_info.throttle_limit, 944 MagickFalse,"B",MagickFormatExtent,resource_limit); 945 break; 946 } 947 case TimeResource: 948 { 949 resource_info.time-=size; 950 (void) FormatMagickSize((MagickSizeType) resource_info.time,MagickFalse, 951 "B",MagickFormatExtent,resource_current); 952 (void) FormatMagickSize((MagickSizeType) resource_info.time_limit, 953 MagickFalse,"B",MagickFormatExtent,resource_limit); 954 break; 955 } 956 default: 957 break; 958 } 959 UnlockSemaphoreInfo(resource_semaphore); 960 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s: %s/%s/%s", 961 CommandOptionToMnemonic(MagickResourceOptions,(ssize_t) type), 962 resource_request,resource_current,resource_limit); 963} 964 965/* 966%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 967% % 968% % 969% % 970% 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 % 971% % 972% % 973% % 974%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 975% 976% RelinquishUniqueFileResource() relinquishes a unique file resource. 977% 978% The format of the RelinquishUniqueFileResource() method is: 979% 980% MagickBooleanType RelinquishUniqueFileResource(const char *path) 981% 982% A description of each parameter follows: 983% 984% o name: the name of the temporary resource. 985% 986*/ 987MagickExport MagickBooleanType RelinquishUniqueFileResource(const char *path) 988{ 989 char 990 cache_path[MagickPathExtent]; 991 992 MagickBooleanType 993 status; 994 995 assert(path != (const char *) NULL); 996 status=MagickFalse; 997 (void) LogMagickEvent(ResourceEvent,GetMagickModule(),"%s",path); 998 if (resource_semaphore == (SemaphoreInfo *) NULL) 999 ActivateSemaphoreInfo(&resource_semaphore); 1000 LockSemaphoreInfo(resource_semaphore); 1001 if (temporary_resources != (SplayTreeInfo *) NULL) 1002 status=DeleteNodeFromSplayTree(temporary_resources, (const void *) path); 1003 UnlockSemaphoreInfo(resource_semaphore); 1004 (void) CopyMagickString(cache_path,path,MagickPathExtent); 1005 AppendImageFormat("cache",cache_path); 1006 (void) ShredFile(cache_path); 1007 if (status == MagickFalse) 1008 status=ShredFile(path); 1009 return(status); 1010} 1011 1012/* 1013%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1014% % 1015% % 1016% % 1017+ R e s o u r c e C o m p o n e n t G e n e s i s % 1018% % 1019% % 1020% % 1021%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1022% 1023% ResourceComponentGenesis() instantiates the resource component. 1024% 1025% The format of the ResourceComponentGenesis method is: 1026% 1027% MagickBooleanType ResourceComponentGenesis(void) 1028% 1029*/ 1030 1031static inline MagickSizeType StringToSizeType(const char *string, 1032 const double interval) 1033{ 1034 double 1035 value; 1036 1037 value=SiPrefixToDoubleInterval(string,interval); 1038 if (value >= (double) MagickULLConstant(~0)) 1039 return(MagickULLConstant(~0)); 1040 return((MagickSizeType) value); 1041} 1042 1043MagickPrivate MagickBooleanType ResourceComponentGenesis(void) 1044{ 1045 char 1046 *limit; 1047 1048 MagickSizeType 1049 memory; 1050 1051 ssize_t 1052 files, 1053 pages, 1054 pagesize; 1055 1056 /* 1057 Set Magick resource limits. 1058 */ 1059 if (resource_semaphore == (SemaphoreInfo *) NULL) 1060 resource_semaphore=AcquireSemaphoreInfo(); 1061 (void) SetMagickResourceLimit(WidthResource,resource_info.width_limit); 1062 limit=GetEnvironmentValue("MAGICK_WIDTH_LIMIT"); 1063 if (limit != (char *) NULL) 1064 { 1065 (void) SetMagickResourceLimit(WidthResource,StringToSizeType(limit, 1066 100.0)); 1067 limit=DestroyString(limit); 1068 } 1069 (void) SetMagickResourceLimit(HeightResource,resource_info.height_limit); 1070 limit=GetEnvironmentValue("MAGICK_HEIGHT_LIMIT"); 1071 if (limit != (char *) NULL) 1072 { 1073 (void) SetMagickResourceLimit(HeightResource,StringToSizeType(limit, 1074 100.0)); 1075 limit=DestroyString(limit); 1076 } 1077 pagesize=GetMagickPageSize(); 1078 pages=(-1); 1079#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) 1080 pages=(ssize_t) sysconf(_SC_PHYS_PAGES); 1081#endif 1082 memory=(MagickSizeType) pages*pagesize; 1083 if ((pagesize <= 0) || (pages <= 0)) 1084 memory=2048UL*1024UL*1024UL; 1085#if defined(PixelCacheThreshold) 1086 memory=PixelCacheThreshold; 1087#endif 1088 (void) SetMagickResourceLimit(AreaResource,2*memory); 1089 limit=GetEnvironmentValue("MAGICK_AREA_LIMIT"); 1090 if (limit != (char *) NULL) 1091 { 1092 (void) SetMagickResourceLimit(AreaResource,StringToSizeType(limit,100.0)); 1093 limit=DestroyString(limit); 1094 } 1095 (void) SetMagickResourceLimit(MemoryResource,memory); 1096 limit=GetEnvironmentValue("MAGICK_MEMORY_LIMIT"); 1097 if (limit != (char *) NULL) 1098 { 1099 (void) SetMagickResourceLimit(MemoryResource, 1100 StringToSizeType(limit,100.0)); 1101 limit=DestroyString(limit); 1102 } 1103 (void) SetMagickResourceLimit(MapResource,2*memory); 1104 limit=GetEnvironmentValue("MAGICK_MAP_LIMIT"); 1105 if (limit != (char *) NULL) 1106 { 1107 (void) SetMagickResourceLimit(MapResource,StringToSizeType(limit,100.0)); 1108 limit=DestroyString(limit); 1109 } 1110 (void) SetMagickResourceLimit(DiskResource,MagickResourceInfinity); 1111 limit=GetEnvironmentValue("MAGICK_DISK_LIMIT"); 1112 if (limit != (char *) NULL) 1113 { 1114 (void) SetMagickResourceLimit(DiskResource,StringToSizeType(limit,100.0)); 1115 limit=DestroyString(limit); 1116 } 1117 files=(-1); 1118#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 1119 files=(ssize_t) sysconf(_SC_OPEN_MAX); 1120#endif 1121#if defined(MAGICKCORE_HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 1122 if (files < 0) 1123 { 1124 struct rlimit 1125 resources; 1126 1127 if (getrlimit(RLIMIT_NOFILE,&resources) != -1) 1128 files=(ssize_t) resources.rlim_cur; 1129 } 1130#endif 1131#if defined(MAGICKCORE_HAVE_GETDTABLESIZE) && defined(MAGICKCORE_POSIX_SUPPORT) 1132 if (files < 0) 1133 files=(ssize_t) getdtablesize(); 1134#endif 1135 if (files < 0) 1136 files=64; 1137 (void) SetMagickResourceLimit(FileResource,MagickMax((size_t) 1138 (3*files/4),64)); 1139 limit=GetEnvironmentValue("MAGICK_FILE_LIMIT"); 1140 if (limit != (char *) NULL) 1141 { 1142 (void) SetMagickResourceLimit(FileResource,StringToSizeType(limit, 1143 100.0)); 1144 limit=DestroyString(limit); 1145 } 1146 (void) SetMagickResourceLimit(ThreadResource,GetOpenMPMaximumThreads()); 1147 limit=GetEnvironmentValue("MAGICK_THREAD_LIMIT"); 1148 if (limit != (char *) NULL) 1149 { 1150 (void) SetMagickResourceLimit(ThreadResource,StringToSizeType(limit, 1151 100.0)); 1152 limit=DestroyString(limit); 1153 } 1154 (void) SetMagickResourceLimit(ThrottleResource,0); 1155 limit=GetEnvironmentValue("MAGICK_THROTTLE_LIMIT"); 1156 if (limit != (char *) NULL) 1157 { 1158 (void) SetMagickResourceLimit(ThrottleResource,StringToSizeType(limit, 1159 100.0)); 1160 limit=DestroyString(limit); 1161 } 1162 (void) SetMagickResourceLimit(TimeResource,MagickResourceInfinity); 1163 limit=GetEnvironmentValue("MAGICK_TIME_LIMIT"); 1164 if (limit != (char *) NULL) 1165 { 1166 (void) SetMagickResourceLimit(TimeResource,StringToSizeType(limit,100.0)); 1167 limit=DestroyString(limit); 1168 } 1169 return(MagickTrue); 1170} 1171 1172/* 1173%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1174% % 1175% % 1176% % 1177+ 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 % 1178% % 1179% % 1180% % 1181%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1182% 1183% ResourceComponentTerminus() destroys the resource component. 1184% 1185% The format of the ResourceComponentTerminus() method is: 1186% 1187% ResourceComponentTerminus(void) 1188% 1189*/ 1190MagickPrivate void ResourceComponentTerminus(void) 1191{ 1192 if (resource_semaphore == (SemaphoreInfo *) NULL) 1193 resource_semaphore=AcquireSemaphoreInfo(); 1194 LockSemaphoreInfo(resource_semaphore); 1195 if (temporary_resources != (SplayTreeInfo *) NULL) 1196 temporary_resources=DestroySplayTree(temporary_resources); 1197 if (random_info != (RandomInfo *) NULL) 1198 random_info=DestroyRandomInfo(random_info); 1199 UnlockSemaphoreInfo(resource_semaphore); 1200 RelinquishSemaphoreInfo(&resource_semaphore); 1201} 1202 1203/* 1204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1205% % 1206% % 1207% % 1208% S e t M a g i c k R e s o u r c e L i m i t % 1209% % 1210% % 1211% % 1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1213% 1214% SetMagickResourceLimit() sets the limit for a particular resource. 1215% 1216% The format of the SetMagickResourceLimit() method is: 1217% 1218% MagickBooleanType SetMagickResourceLimit(const ResourceType type, 1219% const MagickSizeType limit) 1220% 1221% A description of each parameter follows: 1222% 1223% o type: the type of resource. 1224% 1225% o limit: the maximum limit for the resource. 1226% 1227*/ 1228 1229MagickExport MagickBooleanType SetMagickResourceLimit(const ResourceType type, 1230 const MagickSizeType limit) 1231{ 1232 char 1233 *value; 1234 1235 if (resource_semaphore == (SemaphoreInfo *) NULL) 1236 resource_semaphore=AcquireSemaphoreInfo(); 1237 LockSemaphoreInfo(resource_semaphore); 1238 value=(char *) NULL; 1239 switch (type) 1240 { 1241 case WidthResource: 1242 { 1243 resource_info.width_limit=limit; 1244 value=GetPolicyValue("width"); 1245 if (value != (char *) NULL) 1246 resource_info.width_limit=MagickMin(limit,StringToSizeType(value, 1247 100.0)); 1248 break; 1249 } 1250 case HeightResource: 1251 { 1252 resource_info.height_limit=limit; 1253 value=GetPolicyValue("height"); 1254 if (value != (char *) NULL) 1255 resource_info.height_limit=MagickMin(limit,StringToSizeType(value, 1256 100.0)); 1257 break; 1258 } 1259 case AreaResource: 1260 { 1261 resource_info.area_limit=limit; 1262 value=GetPolicyValue("area"); 1263 if (value != (char *) NULL) 1264 resource_info.area_limit=MagickMin(limit,StringToSizeType(value,100.0)); 1265 break; 1266 } 1267 case MemoryResource: 1268 { 1269 resource_info.memory_limit=limit; 1270 value=GetPolicyValue("memory"); 1271 if (value != (char *) NULL) 1272 resource_info.memory_limit=MagickMin(limit,StringToSizeType(value, 1273 100.0)); 1274 break; 1275 } 1276 case MapResource: 1277 { 1278 resource_info.map_limit=limit; 1279 value=GetPolicyValue("map"); 1280 if (value != (char *) NULL) 1281 resource_info.map_limit=MagickMin(limit,StringToSizeType(value,100.0)); 1282 break; 1283 } 1284 case DiskResource: 1285 { 1286 resource_info.disk_limit=limit; 1287 value=GetPolicyValue("disk"); 1288 if (value != (char *) NULL) 1289 resource_info.disk_limit=MagickMin(limit,StringToSizeType(value,100.0)); 1290 break; 1291 } 1292 case FileResource: 1293 { 1294 resource_info.file_limit=limit; 1295 value=GetPolicyValue("file"); 1296 if (value != (char *) NULL) 1297 resource_info.file_limit=MagickMin(limit,StringToSizeType(value,100.0)); 1298 break; 1299 } 1300 case ThreadResource: 1301 { 1302 resource_info.thread_limit=limit; 1303 value=GetPolicyValue("thread"); 1304 if (value != (char *) NULL) 1305 resource_info.thread_limit=MagickMin(limit,StringToSizeType(value, 1306 100.0)); 1307 if (resource_info.thread_limit > GetOpenMPMaximumThreads()) 1308 resource_info.thread_limit=GetOpenMPMaximumThreads(); 1309 else if (resource_info.thread_limit == 0) 1310 resource_info.thread_limit=1; 1311 break; 1312 } 1313 case ThrottleResource: 1314 { 1315 resource_info.throttle_limit=limit; 1316 value=GetPolicyValue("throttle"); 1317 if (value != (char *) NULL) 1318 resource_info.throttle_limit=MagickMin(limit,StringToSizeType(value, 1319 100.0)); 1320 if (resource_info.throttle_limit > GetOpenMPMaximumThreads()) 1321 resource_info.throttle_limit=GetOpenMPMaximumThreads(); 1322 break; 1323 } 1324 case TimeResource: 1325 { 1326 resource_info.time_limit=limit; 1327 value=GetPolicyValue("time"); 1328 if (value != (char *) NULL) 1329 resource_info.time_limit=MagickMin(limit,StringToSizeType(value,100.0)); 1330 ResetPixelCacheEpoch(); 1331 break; 1332 } 1333 default: 1334 break; 1335 } 1336 if (value != (char *) NULL) 1337 value=DestroyString(value); 1338 UnlockSemaphoreInfo(resource_semaphore); 1339 return(MagickTrue); 1340} 1341