#42416 [WFx]: Apache2 locked imagecreate with imagettftext
| From: | baco at infomaniak dot ch | Date: | Mon, 27 Aug 2007 12:33:17 +0000 |
| Subject: | #42416 [WFx]: Apache2 locked imagecreate with imagettftext | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-116720@lists.php.net to get a copy of this message | ||
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] pajoye@php.net
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