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

Reply via email to