ID: 42416 User updated by: baco at infomaniak dot ch Reported By: baco at infomaniak dot ch Status: Wont fix Bug Type: GD related Operating System: Linux PHP Version: 4.4.7 Assigned To: pajoye New Comment:
"The PHP development team hereby announces that support for PHP 4 will continue until the end of this year only." So you need to supported PHP 4 users community until the end of this year right ? I have fixed this bug by backporting mutex changes in gd from 5.2.3 to 4.4.7. No more Apache2 locks. Please include my patch in snap 4.4-dev so it can be included the next 4.4.8 and change the ticket status to Fixed... http://www.infomaniak.ch/php4/unix_gd_mutex.patch Best Regards, Guy Baconniere Reproduce code: --------------- $crash = 1; $text = 'Bug'; $font = $_SERVER['DOCUMENT_ROOT'] . '/fonts' .'/'. 'arial.ttf'; if ($crash == 1) { $image = imagecreate(64, 32); } else { $image = imagecreatetruecolor(64, 32); } $bg = imagecolorallocate($image, 0, 0, 0); $fg = imagecolorallocate($image, 255, 255, 255); /* LOCK APACHE2 PROCESS AFTER THIS POINT IF crash == 1 * => if imagecreate() used but not if imagecreatetruecolor() */ imagettftext($image, 20, 0, 8, 24, $fg, $font, $text); header('Content-type: image/png'); imagepng($image); imagedestroy($image); Proposed patch: --------------- --- ext/gd/config.m4 2007-03-10 14:06:37.000000000 +0100 +++ ext/gd/config.m4 2007-08-27 13:39:51.554453976 +0200 @@ -259,6 +259,7 @@ PHP_CHECK_LIBRARY(gd, gdCacheCreate, [AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_FONTCACHESHUTDOWN,1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdFreeFontCache, [AC_DEFINE(HAVE_GD_FREEFONTCACHE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFontCacheMutexSetup, [AC_DEFINE(HAVE_GD_FONTMUTEX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx, [AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) ]) --- ext/gd/gd.c 2007-01-01 10:46:42.000000000 +0100 +++ ext/gd/gd.c 2007-08-27 13:42:53.257809726 +0200 @@ -333,6 +328,7 @@ #if HAVE_LIBT1 T1_CloseLib(); #endif + gdFontCacheMutexShutdown(); return SUCCESS; } /* }}} */ @@ -344,6 +349,7 @@ { le_gd = zend_register_list_destructors_ex(php_free_gd_image, NULL, "gd", module_number); le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number); + gdFontCacheMutexSetup(); #if HAVE_LIBT1 T1_SetBitmapPad(8); T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE); --- ext/gd/libgd/gd.h 2004-07-23 01:09:24.000000000 +0200 +++ ext/gd/libgd/gd.h 2007-08-27 13:15:04.953547226 +0200 @@ -295,6 +295,14 @@ void gdImageString16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); void gdImageStringUp16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); +/* + * The following functions are required to be called prior to the + * use of any sort of threads in a module load / shutdown function + * respectively. + */ +void gdFontCacheMutexSetup(); +void gdFontCacheMutexShutdown(); + /* 2.0.16: for thread-safe use of gdImageStringFT and friends, * call this before allowing any thread to call gdImageStringFT. * Otherwise it is invoked by the first thread to invoke --- ext/gd/libgd/gdft.c 2007-03-10 13:51:07.000000000 +0100 +++ ext/gd/libgd/gdft.c 2007-08-27 13:14:35.995737476 +0200 @@ -750,10 +750,8 @@ /* find antialised color */ tc_key.bgcolor = *pixel; - gdMutexLock(gdFontCacheMutex); tc_elem = (tweencolor_t *) gdCacheGet (tc_cache, &tc_key); *pixel = tc_elem->tweencolor; - gdMutexUnlock(gdFontCacheMutex); } } } @@ -771,30 +769,39 @@ void gdFontCacheShutdown() { + gdMutexLock(gdFontCacheMutex); + if (fontCache) { - gdMutexLock(gdFontCacheMutex); gdCacheDelete(fontCache); fontCache = NULL; - gdMutexUnlock(gdFontCacheMutex); - gdMutexShutdown(gdFontCacheMutex); FT_Done_FreeType(library); } + + gdMutexUnlock(gdFontCacheMutex); } void gdFreeFontCache() { gdFontCacheShutdown(); } - + +void gdFontCacheMutexSetup() +{ + gdMutexSetup(gdFontCacheMutex); +} + +void gdFontCacheMutexShutdown() +{ + gdMutexShutdown(gdFontCacheMutex); +} + int gdFontCacheSetup(void) { if (fontCache) { /* Already set up */ return 0; } - gdMutexSetup(gdFontCacheMutex); if (FT_Init_FreeType(&library)) { - gdMutexShutdown(gdFontCacheMutex); return -1; } fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease); @@ -856,15 +863,16 @@ /***** initialize font library and font cache on first call ******/ + gdMutexLock(gdFontCacheMutex); if (!fontCache) { if (gdFontCacheSetup() != 0) { gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return "Failure to initialize font library"; } } /*****/ - gdMutexLock(gdFontCacheMutex); /* get the font (via font cache) */ fontkey.fontlist = fontlist; fontkey.library = &library; Previous Comments: ------------------------------------------------------------------------ [2007-08-24 18:19:37] [EMAIL PROTECTED] Workarounds : "- Use imagecreatetruecolor() instead of imagecreate()" The patch is your next comment is not correct. "- Don't use bundled gdlib compile PHP with external gdlib" Either you use the bundled library or the external version. "- Upgrade 5.2.3 who don't have this issue" That's definitively the right choice. Read the PHP4 death announcement on www.php.net. And php 5.2+ has thread safety issues fixed that will never be backported to php4. "--with-ttf --enable-gd-native-ttf " Are you sure you need freetype support? As a side note, I seriously doubt that using php4 with apache2 MPM is a good idea. Anyway, it will not be fixed in 4.x, set status to won't fix. ------------------------------------------------------------------------ [2007-08-24 17:48:01] baco at infomaniak dot ch see diff in gdImageCreate() --- php-4.4.7/ext/gd/libgd/gd.c 2007-08-24 19:39:33.999613335 +0200 +++ php-5.2.3/ext/gd/libgd/gd.c 2007-08-24 19:39:53.052804086 +0200 @@ -5,8 +5,8 @@ im = (gdImage *) gdMalloc(sizeof(gdImage)); memset(im, 0, sizeof(gdImage)); /* Row-major ever since gd 1.3 */ - im->pixels = (unsigned char **) safe_emalloc(sizeof(unsigned char *), sy, 0); - im->AA_opacity = (unsigned char **) safe_emalloc(sizeof(unsigned char *), sy, 0); + im->pixels = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy); + im->AA_opacity = (unsigned char **) gdMalloc(sizeof(unsigned char *) * sy); im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; ------------------------------------------------------------------------ [2007-08-24 16:17:42] baco at infomaniak dot ch Description: ------------ Reproductible with PHP 4.4.7 or with the last Snap 4.4-dev on Apache2 using MPM worker. Apache2 process get locked when calling imagettftext() after calling imagecreate() every call of such code result of another dead locked Apache2 processes. Workarounds : - Use imagecreatetruecolor() instead of imagecreate() - Don't use bundled gdlib compile PHP with external gdlib - Upgrade 5.2.3 who don't have this issue Reproductible with configure \ --with-gd \ --with-png-dir=/usr \ --with-freetype-dir=/usr \ --with-ttf \ --enable-gd-native-ttf \ ... Unreproductible with external gd configure \ --with-gd=/opt/misc/gd \ --with-png-dir=/usr \ --with-jpeg-dir=/usr \ --with-freetype-dir=/usr \ --with-ttf \ --enable-gd-native-ttf \ ... Reproduce code: --------------- $crash = 1; $text = 'Bug'; $font = $_SERVER['DOCUMENT_ROOT'] . '/fonts' .'/'. 'arial.ttf'; if ($crash == 1) { $image = imagecreate(64, 32); } else { $image = imagecreatetruecolor(64, 32); } $white = imagecolorallocate($image, 255, 255, 255); /* LOCK APACHE2 PROCESS AFTER THIS POINT IF crash == 1 * => if imagecreate() used but not if imagecreatetruecolor() */ imagettftext($image, 20, 0, 8, 24, $white, $font, $text); header('Content-type: image/png'); imagepng($image); imagedestroy($image); Expected result: ---------------- Display "Bug" white text on black background Actual result: -------------- Apache2 process get locked and browser wait for the image forever. After it is a matter of time for Apache2 to have all processes locked depending on your ServerLimit and ThreadsPerChild values. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=42416&edit=1