Browse Source

Make array.c thread-safe

experimetnal/RETURN_REF_PATCH
Sascha Schumann 26 years ago
parent
commit
3b515617a4
  1. 79
      ext/standard/array.c
  2. 2
      ext/standard/basic_functions.c
  3. 4
      ext/standard/basic_functions.h
  4. 12
      ext/standard/fsock.c
  5. 6
      ext/standard/string.c

79
ext/standard/array.c

@ -36,13 +36,13 @@
#include "zend_globals.h" #include "zend_globals.h"
#include "php_globals.h" #include "php_globals.h"
#include "php_array.h" #include "php_array.h"
#include "basic_functions.h"
#define EXTR_OVERWRITE 0 #define EXTR_OVERWRITE 0
#define EXTR_SKIP 1 #define EXTR_SKIP 1
#define EXTR_PREFIX_SAME 2 #define EXTR_PREFIX_SAME 2
#define EXTR_PREFIX_ALL 3 #define EXTR_PREFIX_ALL 3
static zval **user_compare_func_name;
static unsigned char all_args_force_ref[] = { 1, BYREF_FORCE_REST }; static unsigned char all_args_force_ref[] = { 1, BYREF_FORCE_REST };
function_entry array_functions[] = { function_entry array_functions[] = {
@ -97,7 +97,7 @@ zend_module_entry array_module_entry = {
array_functions, /* function list */ array_functions, /* function list */
PHP_MINIT(array), /* process startup */ PHP_MINIT(array), /* process startup */
NULL, /* process shutdown */ NULL, /* process shutdown */
PHP_RINIT(array), /* request startup */
NULL, /* request startup */
NULL, /* request shutdown */ NULL, /* request shutdown */
NULL, /* extension info */ NULL, /* extension info */
STANDARD_MODULE_PROPERTIES STANDARD_MODULE_PROPERTIES
@ -115,12 +115,6 @@ PHP_MINIT_FUNCTION(array)
return SUCCESS; return SUCCESS;
} }
PHP_RINIT_FUNCTION(array)
{
user_compare_func_name=NULL;
return SUCCESS;
}
static int array_key_compare(const void *a, const void *b) static int array_key_compare(const void *a, const void *b)
{ {
Bucket *f; Bucket *f;
@ -372,6 +366,7 @@ static int array_user_compare(const void *a, const void *b)
pval **args[2]; pval **args[2];
pval retval; pval retval;
CLS_FETCH(); CLS_FETCH();
BLS_FETCH();
f = *((Bucket **) a); f = *((Bucket **) a);
s = *((Bucket **) b); s = *((Bucket **) b);
@ -379,7 +374,7 @@ static int array_user_compare(const void *a, const void *b)
args[0] = (pval **) f->pData; args[0] = (pval **) f->pData;
args[1] = (pval **) s->pData; args[1] = (pval **) s->pData;
if (call_user_function_ex(CG(function_table), NULL, *user_compare_func_name, &retval, 2, args, 0)==SUCCESS) {
if (call_user_function_ex(CG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args, 0)==SUCCESS) {
convert_to_long(&retval); convert_to_long(&retval);
return retval.value.lval; return retval.value.lval;
} else { } else {
@ -393,24 +388,25 @@ PHP_FUNCTION(usort)
pval **array; pval **array;
pval **old_compare_func; pval **old_compare_func;
HashTable *target_hash; HashTable *target_hash;
BLS_FETCH();
old_compare_func = user_compare_func_name;
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &user_compare_func_name) == FAILURE) {
user_compare_func_name = old_compare_func;
old_compare_func = BG(user_compare_func_name);
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &BG(user_compare_func_name)) == FAILURE) {
BG(user_compare_func_name) = old_compare_func;
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
target_hash = HASH_OF(*array); target_hash = HASH_OF(*array);
if (!target_hash) { if (!target_hash) {
php_error(E_WARNING, "Wrong datatype in usort() call"); php_error(E_WARNING, "Wrong datatype in usort() call");
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
convert_to_string_ex(user_compare_func_name);
convert_to_string_ex(BG(user_compare_func_name));
if (zend_hash_sort(target_hash, qsort, array_user_compare, 1) == FAILURE) { if (zend_hash_sort(target_hash, qsort, array_user_compare, 1) == FAILURE) {
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
RETURN_TRUE; RETURN_TRUE;
} }
@ -419,24 +415,25 @@ PHP_FUNCTION(uasort)
pval **array; pval **array;
pval **old_compare_func; pval **old_compare_func;
HashTable *target_hash; HashTable *target_hash;
BLS_FETCH();
old_compare_func = user_compare_func_name;
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &user_compare_func_name) == FAILURE) {
user_compare_func_name = old_compare_func;
old_compare_func = BG(user_compare_func_name);
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &BG(user_compare_func_name)) == FAILURE) {
BG(user_compare_func_name) = old_compare_func;
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
target_hash = HASH_OF(*array); target_hash = HASH_OF(*array);
if (!target_hash) { if (!target_hash) {
php_error(E_WARNING, "Wrong datatype in uasort() call"); php_error(E_WARNING, "Wrong datatype in uasort() call");
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
convert_to_string_ex(user_compare_func_name);
convert_to_string_ex(BG(user_compare_func_name));
if (zend_hash_sort(target_hash, qsort, array_user_compare, 0) == FAILURE) { if (zend_hash_sort(target_hash, qsort, array_user_compare, 0) == FAILURE) {
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
RETURN_TRUE; RETURN_TRUE;
} }
@ -450,6 +447,7 @@ static int array_user_key_compare(const void *a, const void *b)
pval retval; pval retval;
int status; int status;
CLS_FETCH(); CLS_FETCH();
BLS_FETCH();
args[0] = &key1; args[0] = &key1;
args[1] = &key2; args[1] = &key2;
@ -476,7 +474,7 @@ static int array_user_key_compare(const void *a, const void *b)
key2.type = IS_LONG; key2.type = IS_LONG;
} }
status = call_user_function(CG(function_table), NULL, *user_compare_func_name, &retval, 2, args);
status = call_user_function(CG(function_table), NULL, *BG(user_compare_func_name), &retval, 2, args);
zval_dtor(&key1); zval_dtor(&key1);
zval_dtor(&key2); zval_dtor(&key2);
@ -495,24 +493,25 @@ PHP_FUNCTION(uksort)
pval **array; pval **array;
pval **old_compare_func; pval **old_compare_func;
HashTable *target_hash; HashTable *target_hash;
BLS_FETCH();
old_compare_func = user_compare_func_name;
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &user_compare_func_name) == FAILURE) {
user_compare_func_name = old_compare_func;
old_compare_func = BG(user_compare_func_name);
if (ARG_COUNT(ht) != 2 || getParametersEx(2, &array, &BG(user_compare_func_name)) == FAILURE) {
BG(user_compare_func_name) = old_compare_func;
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
target_hash = HASH_OF(*array); target_hash = HASH_OF(*array);
if (!target_hash) { if (!target_hash) {
php_error(E_WARNING, "Wrong datatype in uksort() call"); php_error(E_WARNING, "Wrong datatype in uksort() call");
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
convert_to_string_ex(user_compare_func_name);
convert_to_string_ex(BG(user_compare_func_name));
if (zend_hash_sort(target_hash, qsort, array_user_key_compare, 0) == FAILURE) { if (zend_hash_sort(target_hash, qsort, array_user_key_compare, 0) == FAILURE) {
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
return; return;
} }
user_compare_func_name = old_compare_func;
BG(user_compare_func_name) = old_compare_func;
RETURN_TRUE; RETURN_TRUE;
} }
@ -770,8 +769,6 @@ PHP_FUNCTION(max)
} }
} }
static zval **php_array_walk_func_name;
static int php_array_walk(HashTable *target_hash, zval **userdata) static int php_array_walk(HashTable *target_hash, zval **userdata)
{ {
zval **args[3], /* Arguments to userland function */ zval **args[3], /* Arguments to userland function */
@ -780,6 +777,7 @@ static int php_array_walk(HashTable *target_hash, zval **userdata)
char *string_key; char *string_key;
ulong num_key; ulong num_key;
CLS_FETCH(); CLS_FETCH();
BLS_FETCH();
/* Allocate space for key */ /* Allocate space for key */
MAKE_STD_ZVAL(key); MAKE_STD_ZVAL(key);
@ -801,7 +799,7 @@ static int php_array_walk(HashTable *target_hash, zval **userdata)
} }
/* Call the userland function */ /* Call the userland function */
call_user_function_ex(CG(function_table), NULL, *php_array_walk_func_name,
call_user_function_ex(CG(function_table), NULL, *BG(array_walk_func_name),
&retval, userdata ? 3 : 2, args, 0); &retval, userdata ? 3 : 2, args, 0);
/* Clean up the key */ /* Clean up the key */
@ -823,23 +821,24 @@ PHP_FUNCTION(array_walk) {
**userdata = NULL, **userdata = NULL,
**old_walk_func_name; **old_walk_func_name;
HashTable *target_hash; HashTable *target_hash;
BLS_FETCH();
argc = ARG_COUNT(ht); argc = ARG_COUNT(ht);
old_walk_func_name = php_array_walk_func_name;
old_walk_func_name = BG(array_walk_func_name);
if (argc < 2 || argc > 3 || if (argc < 2 || argc > 3 ||
getParametersEx(argc, &array, &php_array_walk_func_name, &userdata) == FAILURE) {
php_array_walk_func_name = old_walk_func_name;
getParametersEx(argc, &array, &BG(array_walk_func_name), &userdata) == FAILURE) {
BG(array_walk_func_name) = old_walk_func_name;
WRONG_PARAM_COUNT; WRONG_PARAM_COUNT;
} }
target_hash = HASH_OF(*array); target_hash = HASH_OF(*array);
if (!target_hash) { if (!target_hash) {
php_error(E_WARNING, "Wrong datatype in array_walk() call"); php_error(E_WARNING, "Wrong datatype in array_walk() call");
php_array_walk_func_name = old_walk_func_name;
BG(array_walk_func_name) = old_walk_func_name;
return; return;
} }
convert_to_string_ex(php_array_walk_func_name);
convert_to_string_ex(BG(array_walk_func_name));
php_array_walk(target_hash, userdata); php_array_walk(target_hash, userdata);
php_array_walk_func_name = old_walk_func_name;
BG(array_walk_func_name) = old_walk_func_name;
RETURN_TRUE; RETURN_TRUE;
} }

2
ext/standard/basic_functions.c

@ -394,6 +394,8 @@ PHP_RINIT_FUNCTION(basic)
BG(strtok_string) = NULL; BG(strtok_string) = NULL;
BG(locale_string) = NULL; BG(locale_string) = NULL;
BG(user_compare_func_name) = NULL;
BG(array_walk_func_name) = NULL;
#ifdef HAVE_PUTENV #ifdef HAVE_PUTENV
if (zend_hash_init(&BG(putenv_ht), 1, NULL, (int (*)(void *)) _php3_putenv_destructor, 0) == FAILURE) { if (zend_hash_init(&BG(putenv_ht), 1, NULL, (int (*)(void *)) _php3_putenv_destructor, 0) == FAILURE) {
return FAILURE; return FAILURE;

4
ext/standard/basic_functions.h

@ -111,6 +111,8 @@ typedef struct {
char *strtok_pos1; char *strtok_pos1;
char *strtok_pos2; char *strtok_pos2;
char str_ebuf[40]; char str_ebuf[40];
zval **array_walk_func_name;
zval **user_compare_func_name;
} php_basic_globals; } php_basic_globals;
#ifdef ZTS #ifdef ZTS
@ -120,6 +122,7 @@ typedef struct {
#define BLS_CC , BLS_C #define BLS_CC , BLS_C
#define BG(v) (basic_globals->v) #define BG(v) (basic_globals->v)
#define BLS_FETCH() php_basic_globals *basic_globals = ts_resource(basic_globals_id) #define BLS_FETCH() php_basic_globals *basic_globals = ts_resource(basic_globals_id)
extern int basic_globals_id;
#else #else
#define BLS_D #define BLS_D
#define BLS_DC #define BLS_DC
@ -127,6 +130,7 @@ typedef struct {
#define BLS_CC #define BLS_CC
#define BG(v) (basic_globals.v) #define BG(v) (basic_globals.v)
#define BLS_FETCH() #define BLS_FETCH()
extern php_basic_globals basic_globals;
#endif #endif
#if HAVE_PUTENV #if HAVE_PUTENV

12
ext/standard/fsock.c

@ -149,9 +149,9 @@ int lookup_hostname(const char *addr, struct in_addr *in)
int _php3_is_persistent_sock(int sock) int _php3_is_persistent_sock(int sock)
{ {
char *key; char *key;
PLS_FETCH();
FLS_FETCH();
if (zend_hash_find(&PG(ht_fsock_socks), (char *) &sock, sizeof(sock),
if (zend_hash_find(&FG(ht_fsock_socks), (char *) &sock, sizeof(sock),
(void **) &key) == SUCCESS) { (void **) &key) == SUCCESS) {
return 1; return 1;
} }
@ -245,7 +245,7 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
unsigned short portno; unsigned short portno;
unsigned long conv; unsigned long conv;
char *key = NULL; char *key = NULL;
PLS_FETCH();
FLS_FETCH();
if (arg_count > 5 || arg_count < 2 || getParametersArray(ht,arg_count,args)==FAILURE) { if (arg_count > 5 || arg_count < 2 || getParametersArray(ht,arg_count,args)==FAILURE) {
FREE_SOCK; FREE_SOCK;
@ -282,7 +282,7 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
key = emalloc(args[0]->value.str.len + 10); key = emalloc(args[0]->value.str.len + 10);
sprintf(key, "%s:%d", args[0]->value.str.val, portno); sprintf(key, "%s:%d", args[0]->value.str.val, portno);
if (persistent && zend_hash_find(&PG(ht_fsock_keys), key, strlen(key) + 1,
if (persistent && zend_hash_find(&FG(ht_fsock_keys), key, strlen(key) + 1,
(void *) &sockp) == SUCCESS) { (void *) &sockp) == SUCCESS) {
FREE_SOCK; FREE_SOCK;
*sock = *sockp; *sock = *sockp;
@ -358,9 +358,9 @@ static void _php3_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) {
*sock=socketd; *sock=socketd;
if (persistent) { if (persistent) {
zend_hash_update(&PG(ht_fsock_keys), key, strlen(key) + 1,
zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1,
sock, sizeof(*sock), NULL); sock, sizeof(*sock), NULL);
zend_hash_update(&PG(ht_fsock_socks), (char *) sock, sizeof(*sock),
zend_hash_update(&FG(ht_fsock_socks), (char *) sock, sizeof(*sock),
key, strlen(key) + 1, NULL); key, strlen(key) + 1, NULL);
} }
if(key) efree(key); if(key) efree(key);

6
ext/standard/string.c

@ -33,12 +33,6 @@
#include "zend_execute.h" #include "zend_execute.h"
#include "php_globals.h" #include "php_globals.h"
#ifdef ZTS
extern int basic_globals_id;
#else
extern php_basic_globals basic_globals;
#endif
/* this is read-only, so it's ok */ /* this is read-only, so it's ok */
static char hexconvtab[] = "0123456789abcdef"; static char hexconvtab[] = "0123456789abcdef";

Loading…
Cancel
Save