amfext的bug已经不知道发现第几次了,这次的bug主要是在使用脚本进行压力测试时发现程序内存会一直增长,最终定位到amfext,如果是以php-cgi方式运行的话,一次请求不会有多次amf_encode和amf_decode调用,因此问题不是很大,因为amfext遵守了php扩展的开发方法,使用了emalloc来分配 内存,因此在RSHUTDOWN时会自动清理,但是如果是用脚本的话,程序很快就会因为内存持续增长也挂掉。
加上与之前amfext的修改,patch如下
--- amfext-0.9.2/amf.c 2008-07-18 18:28:36.000000000 +0800
+++ amfext/amf.c 2011-12-01 13:33:12.000000000 +0800
@@ -137,7 +137,8 @@ static void amf_zval_dtor(void *p)
static void amf_class_dtor(void *p)
{
zval **zval_ptr = (zval**)p;
- zval_dtor(*zval_ptr);
+ //zval_dtor(*zval_ptr);
+ zval_ptr_dtor(zval_ptr);
}
/** context of serialization */
@@ -473,9 +474,9 @@ static void amf_serialize_output_get(amf
{
amf_string_part * cur,* head;
char * cp,*bcp;
- ZVAL_EMPTY_STRING(result);
if(buf->length == 0)
{
+ ZVAL_EMPTY_STRING(result);
return;
}
cp = bcp = guard_emalloc(buf->length);
@@ -510,6 +511,7 @@ static void amf_serialize_output_get(amf
}
while(cur != head);
ZVAL_STRINGL(result, bcp, buf->length,1);
+ efree(bcp);
}
/** destructor of the buffer */
@@ -557,9 +559,9 @@ typedef amf_serialize_output_t *amf_seri
/** initializes a zval to a HashTable of zval with a possible number of items */
static int amf_array_init(zval *arg, int count TSRMLS_DC)
{
- ALLOC_HASHTABLE_REL(arg->value.ht);
+ ALLOC_HASHTABLE(arg->value.ht);
- zend_hash_init(arg->value.ht, count, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
+ zend_hash_init(arg->value.ht, count, NULL, ZVAL_PTR_DTOR, 0);
arg->type = IS_ARRAY;
return SUCCESS;
}
@@ -844,7 +846,7 @@ static inline void amf_write_zstring(amf
buf->last_chunk->size = 1; /* zval chun */
buf->last_chunk->zv = zstr;
- ZVAL_ADDREF(zstr);
+ Z_ADDREF_P(zstr);
buf->chunks++;
buf->left_in_part -= sizeof(amf_string_chunk);
@@ -1185,7 +1187,7 @@ static void amf3_serialize_object(amf_se
int resultType = AMFC_TYPEDOBJECT;
int resultValueLength = 0;
zval** resultValue = struc;
- int deallocResult = (*struc)->refcount;
+ int deallocResult = Z_REFCOUNT_PP(struc);
resultType = amf_perform_serialize_callback(struc, &className,&classNameLen,&resultValue,var_hash TSRMLS_CC);
@@ -2390,6 +2392,7 @@ PHP_FUNCTION(amf_encode)
tpbuf = (amf_serialize_output) zend_fetch_resource( zzOutputSB TSRMLS_CC, -1, PHP_AMF_STRING_BUILDER_RES_NAME, NULL, 1, amf_serialize_output_resource_reg);
if(tpbuf != NULL)
{
+ amf_serialize_output_dtor(pbuf);
pbuf = tpbuf;
asSB = 1;
/* ZVAL_ADDREF(*zzOutputSB) */
@@ -2429,7 +2432,7 @@ PHP_FUNCTION(amf_encode)
}
/* deallocate if it was wast */
- if(asSB == 1)
+ if(asSB != 1)
{
amf_serialize_output_dtor(&buf);
}
@@ -2440,8 +2443,8 @@ PHP_FUNCTION(amf_encode)
RETURN_STRINGL(membuf, memsize, 1);
php_stream_close(pbuf);
}
- amf_SERIALIZE_DTOR(var_hash,zzCallback)
#endif
+ amf_SERIALIZE_DTOR(var_hash,zzCallback)
}
/* Decoding {{{1*/
@@ -2670,7 +2673,7 @@ static int amf3_read_string(zval **rval,
}
else
{
- newval->refcount--;
+ Z_DELREF_P(newval);
}
*rval = newval;
}
@@ -2772,6 +2775,7 @@ static int amf_read_objectdata(zval **rv
break;
}
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf_var_unserialize(&zValue,p, max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf cannot unserialize key <%s>",Z_STRVAL_P(zName));
@@ -2824,7 +2828,7 @@ static int amf_read_objectdata(zval **rv
{
if(zClassname != NULL)
{
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_assoc_zval(*rval, "_explicitType",zClassname);
}
}
@@ -2859,6 +2863,7 @@ static int amf3_unserialize_var(zval **r
case AMF3_NUMBER:
ZVAL_DOUBLE(*rval, amf_read_double(p, max, var_hash)); break;
case AMF3_STRING:
+ zval_ptr_dtor(rval);
if(amf3_read_string(rval, p, max, 1, AMF_STRING_AS_TEXT,var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf cannot lookup string");
@@ -2906,8 +2911,8 @@ static int amf3_unserialize_var(zval **r
{
int iIndex;
int maxIndex = handle >> 1;
- HashTable * htOutput = HASH_OF(*rval);
amf_array_init(*rval, maxIndex TSRMLS_CC);
+ HashTable * htOutput = HASH_OF(*rval);
/* zval_add_ref(rval) */
amf_put_in_cache(&(var_hash->objects),*rval);
@@ -2927,6 +2932,7 @@ static int amf3_unserialize_var(zval **r
break;
}
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf cannot unserialize key %s",Z_STRVAL_P(zKey));
@@ -2967,6 +2973,7 @@ static int amf3_unserialize_var(zval **r
{
zval * zValue;
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max,var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3045,7 +3052,7 @@ static int amf3_unserialize_var(zval **r
MAKE_STD_ZVAL(zClassDef);
amf_array_init(zClassDef,nClassMemberCount+2 TSRMLS_CC);
add_next_index_long(zClassDef,(bTypedObject?1:0)|nClassMemberCount << AMF_CLASS_MEMBERCOUNT_SHIFT |iDynamicObject|iExternalizable);
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_next_index_zval(zClassDef, zClassname);
/* loop over classMemberCoun */
@@ -3056,7 +3063,7 @@ static int amf3_unserialize_var(zval **r
{
break;
}
- ZVAL_ADDREF(zMemberName);
+ Z_ADDREF_P(zMemberName);
add_next_index_zval(zClassDef,zMemberName); /* pass referenc */
}
@@ -3148,6 +3155,7 @@ static int amf3_unserialize_var(zval **r
return FAILURE;
}
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3180,6 +3188,7 @@ static int amf3_unserialize_var(zval **r
break;
}
MAKE_STD_ZVAL(zValue)
+ zValue->type = 0;
if(amf3_unserialize_var(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
zval_ptr_dtor(&zValue);
@@ -3201,7 +3210,7 @@ static int amf3_unserialize_var(zval **r
{
if(bTypedObject != 0)
{
- ZVAL_ADDREF(zClassname);
+ Z_ADDREF_P(zClassname);
add_assoc_zval(*rval, "_explicitType",zClassname);
}
}
@@ -3300,6 +3309,7 @@ static int amf_var_unserialize(zval **rv
{
zval * zValue;
MAKE_STD_ZVAL(zValue);
+ zValue->type = 0;
if(amf_var_unserialize(&zValue,p,max, var_hash TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "amf bad unserialized value for array index %d",iIndex);