mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
Reentrancy fixes
This commit is contained in:
parent
5c13954eed
commit
629bc67086
6 changed files with 242 additions and 114 deletions
151
ext/java/java.c
151
ext/java/java.c
|
@ -68,12 +68,33 @@ static char *javahome = 0;
|
|||
static char *javalib = 0;
|
||||
|
||||
static int iniUpdated = 0;
|
||||
|
||||
static JavaVM *jvm = 0;
|
||||
static JNIEnv *jenv = 0;
|
||||
static jclass php_reflect;
|
||||
static void *dl_handle = 0;
|
||||
|
||||
typedef struct {
|
||||
JavaVM *jvm;
|
||||
JNIEnv *jenv;
|
||||
jobject php_reflect;
|
||||
jclass reflect_class;
|
||||
} php_java_globals;
|
||||
|
||||
#ifdef ZTS
|
||||
#define JG(v) (java_globals->v)
|
||||
#define JG_FETCH() php_java_globals *java_globals = ts_resource(java_globals_id)
|
||||
#define JG_D php_java_globals *java_globals
|
||||
#define JG_DC , JG_D
|
||||
#define JG_C dir_globals
|
||||
#define JG_CC , JG_C
|
||||
int java_globals_id;
|
||||
#else
|
||||
#define JG(v) (java_globals.v)
|
||||
#define JG_FETCH()
|
||||
#define JG_D
|
||||
#define JG_DC
|
||||
#define JG_C
|
||||
#define JG_CC
|
||||
php_java_globals javadir_globals;
|
||||
#endif
|
||||
|
||||
static zend_class_entry java_class_entry;
|
||||
|
||||
static PHP_INI_MH(OnIniUpdate) {
|
||||
|
@ -106,15 +127,17 @@ PHP_INI_END()
|
|||
* Destroy a Java Virtual Machine.
|
||||
*/
|
||||
void jvm_destroy() {
|
||||
if (php_reflect) (*jenv)->DeleteGlobalRef(jenv, php_reflect);
|
||||
if (jvm) {
|
||||
(*jvm)->DetachCurrentThread(jvm);
|
||||
(*jvm)->DestroyJavaVM(jvm);
|
||||
jvm = 0;
|
||||
JG_FETCH();
|
||||
|
||||
if (JG(php_reflect)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), JG(php_reflect));
|
||||
if (JG(jvm)) {
|
||||
(*JG(jvm))->DetachCurrentThread(JG(jvm));
|
||||
(*JG(jvm))->DestroyJavaVM(JG(jvm));
|
||||
JG(jvm) = 0;
|
||||
}
|
||||
if (dl_handle) DL_UNLOAD(dl_handle);
|
||||
php_reflect = 0;
|
||||
jenv = 0;
|
||||
JG(php_reflect) = 0;
|
||||
JG(jenv) = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -134,9 +157,10 @@ static void addJVMOption(JavaVMInitArgs *vm_args, char *name, char *value) {
|
|||
#endif
|
||||
|
||||
static int jvm_create() {
|
||||
JG_FETCH();
|
||||
|
||||
int rc;
|
||||
jclass local_php_reflect;
|
||||
jobject local_php_reflect;
|
||||
jthrowable error;
|
||||
|
||||
jint (JNICALL *JNI_CreateVM)(const void*,const void*,void*);
|
||||
|
@ -217,21 +241,22 @@ static int jvm_create() {
|
|||
|
||||
#endif
|
||||
|
||||
rc = (*JNI_CreateVM)(&jvm, &jenv, &vm_args);
|
||||
rc = (*JNI_CreateVM)(&JG(jvm), &JG(jenv), &vm_args);
|
||||
|
||||
if (rc) {
|
||||
php_error(E_ERROR, "Unable to create Java Virtual Machine");
|
||||
return rc;
|
||||
}
|
||||
|
||||
local_php_reflect = (*jenv)->FindClass(jenv, "net/php/reflect");
|
||||
error = (*jenv)->ExceptionOccurred(jenv);
|
||||
JG(reflect_class) = (*JG(jenv))->FindClass(JG(jenv), "net/php/reflect");
|
||||
error = (*JG(jenv))->ExceptionOccurred(JG(jenv));
|
||||
if (error) {
|
||||
jclass errClass;
|
||||
jmethodID toString;
|
||||
jobject errString;
|
||||
const char *errAsUTF;
|
||||
jboolean isCopy;
|
||||
JNIEnv *jenv = JG(jenv);
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
errClass = (*jenv)->GetObjectClass(jenv, error);
|
||||
toString = (*jenv)->GetMethodID(jenv, errClass, "toString",
|
||||
|
@ -244,13 +269,17 @@ static int jvm_create() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
php_reflect = (*jenv)->NewGlobalRef(jenv, local_php_reflect);
|
||||
local_php_reflect = (*JG(jenv))->AllocObject(JG(jenv), JG(reflect_class));
|
||||
JG(php_reflect) = (*JG(jenv))->NewGlobalRef(JG(jenv), local_php_reflect);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static jobjectArray _java_makeArray(int argc, pval** argv) {
|
||||
JG_FETCH();
|
||||
JNIEnv *jenv = JG(jenv);
|
||||
|
||||
jclass objectClass = (*jenv)->FindClass(jenv, "java/lang/Object");
|
||||
jobjectArray result = (*jenv)->NewObjectArray(jenv, argc, objectClass, 0);
|
||||
jobject arg;
|
||||
|
@ -273,23 +302,23 @@ static jobjectArray _java_makeArray(int argc, pval** argv) {
|
|||
break;
|
||||
|
||||
case IS_BOOL:
|
||||
makeArg = (*jenv)->GetStaticMethodID(jenv, php_reflect, "MakeArg",
|
||||
makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
|
||||
"(Z)Ljava/lang/Object;");
|
||||
arg = (*jenv)->CallStaticObjectMethod(jenv, php_reflect, makeArg,
|
||||
arg = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
|
||||
(jboolean)(argv[i]->value.lval));
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
makeArg = (*jenv)->GetStaticMethodID(jenv, php_reflect, "MakeArg",
|
||||
makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
|
||||
"(J)Ljava/lang/Object;");
|
||||
arg = (*jenv)->CallStaticObjectMethod(jenv, php_reflect, makeArg,
|
||||
arg = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
|
||||
(jlong)(argv[i]->value.lval));
|
||||
break;
|
||||
|
||||
case IS_DOUBLE:
|
||||
makeArg = (*jenv)->GetStaticMethodID(jenv, php_reflect, "MakeArg",
|
||||
makeArg = (*jenv)->GetMethodID(jenv, JG(reflect_class), "MakeArg",
|
||||
"(D)Ljava/lang/Object;");
|
||||
arg = (*jenv)->CallStaticObjectMethod(jenv, php_reflect, makeArg,
|
||||
arg = (*jenv)->CallObjectMethod(jenv, JG(php_reflect), makeArg,
|
||||
(jdouble)(argv[i]->value.dval));
|
||||
break;
|
||||
|
||||
|
@ -323,6 +352,9 @@ static int checkError(pval *value) {
|
|||
void java_call_function_handler
|
||||
(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
|
||||
{
|
||||
JG_FETCH();
|
||||
JNIEnv *jenv;
|
||||
|
||||
pval *object = property_reference->object;
|
||||
zend_overloaded_element *function_name = (zend_overloaded_element *)
|
||||
property_reference->elements_list->tail->data;
|
||||
|
@ -333,9 +365,10 @@ void java_call_function_handler
|
|||
pval **arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
|
||||
getParametersArray(ht, arg_count, arguments);
|
||||
|
||||
if (iniUpdated && jenv) jvm_destroy();
|
||||
if (!jenv) jvm_create();
|
||||
if (!jenv) return;
|
||||
if (iniUpdated && JG(jenv)) jvm_destroy();
|
||||
if (!JG(jenv)) jvm_create();
|
||||
if (!JG(jenv)) return;
|
||||
jenv = JG(jenv);
|
||||
|
||||
if (!strcmp("java",function_name->element.value.str.val)) {
|
||||
|
||||
|
@ -343,12 +376,12 @@ void java_call_function_handler
|
|||
First argument is the class name. Any additional arguments will
|
||||
be treated as constructor parameters. */
|
||||
|
||||
jmethodID co = (*jenv)->GetStaticMethodID(jenv, php_reflect, "CreateObject",
|
||||
jmethodID co = (*jenv)->GetMethodID(jenv, JG(reflect_class), "CreateObject",
|
||||
"(Ljava/lang/String;[Ljava/lang/Object;J)V");
|
||||
jstring className=(*jenv)->NewStringUTF(jenv, arguments[0]->value.str.val);
|
||||
(pval*)(long)result = object;
|
||||
|
||||
(*jenv)->CallStaticVoidMethod(jenv, php_reflect, co,
|
||||
(*jenv)->CallVoidMethod(jenv, JG(php_reflect), co,
|
||||
className, _java_makeArray(arg_count-1, arguments+1), result);
|
||||
|
||||
(*jenv)->DeleteLocalRef(jenv, className);
|
||||
|
@ -362,14 +395,14 @@ void java_call_function_handler
|
|||
|
||||
/* invoke a method on the given object */
|
||||
|
||||
jmethodID invoke = (*jenv)->GetStaticMethodID(jenv, php_reflect, "Invoke",
|
||||
jmethodID invoke = (*jenv)->GetMethodID(jenv, JG(reflect_class), "Invoke",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;J)V");
|
||||
zend_hash_index_find(object->value.obj.properties, 0, (void**) &handle);
|
||||
obj = zend_list_find((*handle)->value.lval, &type);
|
||||
method = (*jenv)->NewStringUTF(jenv, function_name->element.value.str.val);
|
||||
(pval*)(long)result = return_value;
|
||||
|
||||
(*jenv)->CallStaticVoidMethod(jenv, php_reflect, invoke,
|
||||
(*jenv)->CallVoidMethod(jenv, JG(php_reflect), invoke,
|
||||
obj, method, _java_makeArray(arg_count, arguments), result);
|
||||
|
||||
(*jenv)->DeleteLocalRef(jenv, method);
|
||||
|
@ -386,30 +419,38 @@ void java_call_function_handler
|
|||
|
||||
PHP_FUNCTION(java_last_exception_get)
|
||||
{
|
||||
JG_FETCH();
|
||||
|
||||
jlong result = 0;
|
||||
jmethodID lastEx;
|
||||
|
||||
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
|
||||
|
||||
(pval*)(long)result = return_value;
|
||||
|
||||
lastEx = (*jenv)->GetStaticMethodID(jenv, php_reflect, "lastException",
|
||||
"(J)V");
|
||||
lastEx = (*JG(jenv))->GetMethodID(JG(jenv), JG(reflect_class),
|
||||
"lastException", "(J)V");
|
||||
|
||||
(*jenv)->CallStaticVoidMethod(jenv, php_reflect, lastEx, result);
|
||||
(*JG(jenv))->CallVoidMethod(JG(jenv), JG(php_reflect), lastEx, result);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
PHP_FUNCTION(java_last_exception_clear)
|
||||
{
|
||||
JG_FETCH();
|
||||
|
||||
jlong result = 0;
|
||||
jmethodID clearEx;
|
||||
|
||||
if (ZEND_NUM_ARGS()!=0) WRONG_PARAM_COUNT;
|
||||
|
||||
(pval*)(long)result = return_value;
|
||||
|
||||
clearEx = (*jenv)->GetStaticMethodID(jenv, php_reflect, "clearException",
|
||||
"()V");
|
||||
clearEx = (*JG(jenv))->GetMethodID(JG(jenv), JG(reflect_class),
|
||||
"clearException", "()V");
|
||||
|
||||
(*jenv)->CallStaticVoidMethod(jenv, php_reflect, clearEx);
|
||||
(*JG(jenv))->CallVoidMethod(JG(jenv), JG(php_reflect), clearEx);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -417,6 +458,9 @@ PHP_FUNCTION(java_last_exception_clear)
|
|||
static pval _java_getset_property
|
||||
(zend_property_reference *property_reference, jobjectArray value)
|
||||
{
|
||||
JG_FETCH();
|
||||
JNIEnv *jenv = JG(jenv);
|
||||
|
||||
pval presult;
|
||||
jlong result = 0;
|
||||
pval **pobject;
|
||||
|
@ -441,10 +485,10 @@ static pval _java_getset_property
|
|||
"Attempt to access a Java property on a non-Java object");
|
||||
} else {
|
||||
/* invoke the method */
|
||||
jmethodID gsp = (*jenv)->GetStaticMethodID(jenv, php_reflect, "GetSetProp",
|
||||
jmethodID gsp = (*jenv)->GetMethodID(jenv, JG(reflect_class), "GetSetProp",
|
||||
"(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;J)V");
|
||||
(*jenv)->CallStaticVoidMethod
|
||||
(jenv, php_reflect, gsp, obj, propName, value, result);
|
||||
(*jenv)->CallVoidMethod
|
||||
(jenv, JG(php_reflect), gsp, obj, propName, value, result);
|
||||
}
|
||||
|
||||
(*jenv)->DeleteLocalRef(jenv, propName);
|
||||
|
@ -472,9 +516,16 @@ int java_set_property_handler
|
|||
/***************************************************************************/
|
||||
|
||||
static void _php_java_destructor(void *jobject) {
|
||||
if (jenv) (*jenv)->DeleteGlobalRef(jenv, jobject);
|
||||
JG_FETCH();
|
||||
if (JG(jenv)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), jobject);
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
static void alloc_java_globals_ctor(php_java_globals *java_globals) {
|
||||
memset(java_globals, 0, sizeof(php_java_globals));
|
||||
}
|
||||
#endif
|
||||
|
||||
PHP_MINIT_FUNCTION(java) {
|
||||
INIT_OVERLOADED_CLASS_ENTRY(java_class_entry, "java", NULL,
|
||||
java_call_function_handler,
|
||||
|
@ -494,13 +545,19 @@ PHP_MINIT_FUNCTION(java) {
|
|||
libpath=PG(extension_dir);
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
java_globals_id = ts_allocate_id(sizeof(php_java_globals),
|
||||
(ts_allocate_ctor)alloc_java_globals_ctor, NULL);
|
||||
#endif
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
PHP_MSHUTDOWN_FUNCTION(java) {
|
||||
JG_FETCH();
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
if (jvm) jvm_destroy();
|
||||
if (JG(jvm)) jvm_destroy();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -620,8 +677,16 @@ JNIEXPORT void JNICALL Java_net_php_reflect_setException
|
|||
JNIEXPORT void JNICALL Java_net_php_reflect_setEnv
|
||||
(JNIEnv *newJenv, jclass self)
|
||||
{
|
||||
JG_FETCH();
|
||||
jobject local_php_reflect;
|
||||
|
||||
iniUpdated=0;
|
||||
jenv=newJenv;
|
||||
if (!self) self = (*jenv)->FindClass(jenv, "net/php/reflect");
|
||||
php_reflect = (*jenv)->NewGlobalRef(jenv, self);
|
||||
JG(jenv)=newJenv;
|
||||
|
||||
if (!self) self = (*JG(jenv))->FindClass(JG(jenv), "net/php/reflect");
|
||||
JG(reflect_class) = self;
|
||||
|
||||
if (JG(php_reflect)) (*JG(jenv))->DeleteGlobalRef(JG(jenv), JG(php_reflect));
|
||||
local_php_reflect = (*JG(jenv))->AllocObject(JG(jenv), JG(reflect_class));
|
||||
JG(php_reflect) = (*JG(jenv))->NewGlobalRef(JG(jenv), local_php_reflect);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue