Skip to content

Commit d6326e5

Browse files
drswingheadkitech
authored andcommitted
fix duplicate register when two or more modules loaded
1 parent cec7fd6 commit d6326e5

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

phpgo/extension.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,11 @@ int zend_add_function(int cidx, int fidx, int cbid, char *name, char *atys, int
653653
printf("add func %s at %d:%d=%d, atys=%s, rety=%d\n",
654654
name, cidx, fidx, cbid, atys, rety);
655655

656+
// TODO 检测是否是phpgo注册的?
657+
if (gozend_function_registered(name) == 1) {
658+
dlog_debug("function already exists: %s", name);
659+
}
660+
656661
int cnlen = strlen(GLOBAL_VCLASS_NAME);
657662
char *cname = GLOBAL_VCLASS_NAME;
658663
char *mname = name;

phpgo/extension.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package phpgo
33
/*
44
#include "extension.h"
55
#include "../zend/compat.h"
6+
#include "../zend/szend.h"
67
78
#include <php.h>
89
#include <zend_exceptions.h>
@@ -19,9 +20,10 @@ import "errors"
1920
import "fmt"
2021
import "log"
2122
import "os"
22-
import "github.com/kitech/php-go/zend"
2323
import "strings"
2424

25+
import "github.com/kitech/php-go/zend"
26+
2527
// 一个程序只能创建一个扩展
2628
// 所以使用全局变量也没有问题。
2729
var (
@@ -336,11 +338,22 @@ func AddConstant(name string, val interface{}, namespace interface{}) {
336338
// 内置函数注册,内置类注册。
337339
func addBuiltins() {
338340
// nice fix exit crash bug.
339-
AddFunc("GoExit", func(code int) { os.Exit(code) })
340-
AddFunc("GoGo", func(fn interface{}) { log.Println(fn) })
341-
AddFunc("GoPanic", func() { panic("got") })
342-
AddFunc("GoRecover", func() { recover() })
343-
AddFunc("GoPrintln", func(p0 int, v interface{}) { log.Println(v, 123333) })
341+
var iret C.int = 0
342+
if iret = C.gozend_function_registered(C.CString("GoExit")); iret == C.int(0) {
343+
AddFunc("GoExit", func(code int) { os.Exit(code) })
344+
}
345+
if iret = C.gozend_function_registered(C.CString("GoGo")); iret == C.int(0) {
346+
AddFunc("GoGo", func(fn interface{}) { log.Println(fn) })
347+
}
348+
if iret = C.gozend_function_registered(C.CString("GoPanic")); iret == C.int(0) {
349+
AddFunc("GoPanic", func() { panic("got") })
350+
}
351+
if iret = C.gozend_function_registered(C.CString("GoRecover")); iret == C.int(0) {
352+
AddFunc("GoRecover", func() { recover() })
353+
}
354+
if iret = C.gozend_function_registered(C.CString("GoPrintln")); iret == C.int(0) {
355+
AddFunc("GoPrintln", func(p0 int, v interface{}) { log.Println(v, 123333) })
356+
}
344357
}
345358

346359
// 注册php module 初始化函数

zend/szend.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,44 @@ void call_user_function_callback(char *data)
183183
// zval_ptr_dtor(&retval_ptr);
184184
zval_dtor(&function_name);
185185
}
186+
187+
// find function name in HashTable
188+
static int _gozend_function_exists_ht(char *fname, HashTable* ht) {
189+
zend_string *name;
190+
zend_function *func;
191+
zend_string *lcname;
192+
193+
name = zend_string_init(fname, strlen(fname), 0);
194+
195+
if (ZSTR_VAL(name)[0] == '\\') {
196+
/* Ignore leading "\" */
197+
lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
198+
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
199+
} else {
200+
lcname = zend_string_tolower(name);
201+
}
202+
203+
func = zend_hash_find_ptr(ht, lcname);
204+
zend_string_release(lcname);
205+
zend_string_release(name);
206+
207+
/*
208+
* A bit of a hack, but not a bad one: we see if the handler of the function
209+
* is actually one that displays "function is disabled" message.
210+
*/
211+
if (func && (func->type != ZEND_INTERNAL_FUNCTION ||
212+
func->internal_function.handler != zif_display_disabled_function)) {
213+
return 1;
214+
} else {
215+
return 0;
216+
}
217+
}
218+
219+
// seems only can be used when vm executing
220+
int gozend_function_exists(char *fname) {
221+
return _gozend_function_exists_ht(fname, executor_globals.function_table);
222+
}
223+
224+
int gozend_function_registered(char *fname) {
225+
return _gozend_function_exists_ht(fname, compiler_globals.function_table);
226+
}

zend/szend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ extern void *gozend_ecalloc(size_t nmemb, size_t size);
1414
extern void *gozend_erealloc(void *ptr, size_t size);
1515
extern char gozend_eval_string(char *code);
1616
extern void call_user_function_callback(char *arg);
17+
extern int gozend_function_exists(char *fname);
18+
extern int gozend_function_registered(char *fname);
1719

1820
#endif

0 commit comments

Comments
 (0)