Skip to content

Commit 2db64d8

Browse files
committed
Free memory
1 parent 76e9d5f commit 2db64d8

File tree

7 files changed

+102
-30
lines changed

7 files changed

+102
-30
lines changed

ext/module.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static char* find_php_go_call_fun(PHPGoCallFun *fun, void *handle) {
4040
return NULL;
4141
}
4242

43-
char* phpgo_load(phpgo_module **module_pp, const char *path, const char *name) {
43+
char* phpgo_module_load(phpgo_module **module_pp, const char *path, const char *name) {
4444

4545
char *err;
4646
void *handle;
@@ -52,7 +52,7 @@ char* phpgo_load(phpgo_module **module_pp, const char *path, const char *name) {
5252

5353
handle = dlopen(path, RTLD_NOW);
5454
if (!handle) {
55-
return dlerror();
55+
return estrdup(dlerror());
5656
}
5757

5858
err = find_php_go_exports_fun(&php_go_exports_fun, handle);
@@ -94,3 +94,11 @@ char* phpgo_load(phpgo_module **module_pp, const char *path, const char *name) {
9494

9595
return NULL;
9696
}
97+
98+
void phpgo_module_free(phpgo_module *module) {
99+
efree(module->name);
100+
zend_hash_destroy(&module->exports);
101+
efree(module);
102+
}
103+
104+

ext/module.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ typedef struct {
2929
PHPGoCallFun php_go_call_fun;
3030
} phpgo_module;
3131

32-
char* phpgo_load(phpgo_module **module_pp, const char *path, const char *name);
32+
char* phpgo_module_load(phpgo_module **module_pp, const char *path, const char *name);
33+
void phpgo_module_free(phpgo_module *module);
3334

3435
#endif /* MODULE_H */
3536

ext/module_class.c

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ typedef struct {
2626

2727
zend_object_handlers module_object_handlers;
2828

29+
void module_free(void *object TSRMLS_DC) /* {{{ */
30+
{
31+
module_intern *intern = (module_intern*)object;
32+
phpgo_module_free(intern->module);
33+
efree(intern);
34+
}
35+
/* }}} */
36+
2937
static zend_object_value module_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
3038
{
3139
zend_object_value retval;
@@ -35,7 +43,7 @@ static zend_object_value module_new(zend_class_entry *class_type TSRMLS_DC) /* {
3543
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
3644
object_properties_init(&intern->std, class_type);
3745

38-
retval.handle = zend_objects_store_put(&intern->std, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
46+
retval.handle = zend_objects_store_put(&intern->std, (zend_objects_store_dtor_t) zend_objects_destroy_object, module_free, NULL TSRMLS_CC);
3947
retval.handlers = &module_object_handlers;
4048

4149
return retval;
@@ -44,14 +52,14 @@ static zend_object_value module_new(zend_class_entry *class_type TSRMLS_DC) /* {
4452

4553
PHP_METHOD(PHPGo__Module, __fun)
4654
{
47-
zval ***args;
55+
zval ***args = NULL;
4856
int argc;
4957
const char *fname;
5058
module_intern *intern;
5159
php_export **pexport;
5260
php_export *export;
53-
php_arg *ins;
54-
php_arg *outs;
61+
php_arg *ins = NULL;
62+
php_arg *outs = NULL;
5563
zend_function *active_function = EG(current_execute_data)->function_state.function;
5664
int i;
5765

@@ -64,7 +72,7 @@ PHP_METHOD(PHPGo__Module, __fun)
6472

6573
if (zend_hash_find(&intern->module->exports, fname, strlen(fname)+1, (void**)&pexport) != SUCCESS) {
6674
php_error(E_ERROR, "Internal error: couldn't find export named `%s`", fname);
67-
return;
75+
goto out;
6876
}
6977

7078
export = *pexport;
@@ -82,7 +90,7 @@ PHP_METHOD(PHPGo__Module, __fun)
8290
export->num_ins == 1 ? "" : "s",
8391
argc
8492
);
85-
return;
93+
goto out;
8694
}
8795

8896
ins = ecalloc(export->num_ins, sizeof(*ins));
@@ -93,7 +101,7 @@ PHP_METHOD(PHPGo__Module, __fun)
93101
case PHPGO_KIND_BOOL: {
94102
zend_bool b;
95103
if (zend_parse_parameter(0, i+1 TSRMLS_CC, args[i], "b", &b) != SUCCESS) {
96-
return;
104+
goto out;
97105
}
98106
ins[i].b = b;
99107
break;
@@ -108,7 +116,7 @@ PHP_METHOD(PHPGo__Module, __fun)
108116
case PHPGO_KIND_UINT64: {
109117
long l;
110118
if (zend_parse_parameter(0, i+1 TSRMLS_CC, args[i], "l", &l) != SUCCESS) {
111-
return;
119+
goto out;
112120
}
113121
ins[i].l = l;
114122
break;
@@ -117,7 +125,7 @@ PHP_METHOD(PHPGo__Module, __fun)
117125
case PHPGO_KIND_FLOAT64: {
118126
double d;
119127
if (zend_parse_parameter(0, i+1 TSRMLS_CC, args[i], "d", &d) != SUCCESS) {
120-
return;
128+
goto out;
121129
}
122130
ins[i].d = d;
123131
break;
@@ -126,7 +134,7 @@ PHP_METHOD(PHPGo__Module, __fun)
126134
char *s;
127135
int l;
128136
if (zend_parse_parameter(0, i+1 TSRMLS_CC, args[i], "s", &s, &l) != SUCCESS) {
129-
return;
137+
goto out;
130138
}
131139
ins[i].s.s = s;
132140
ins[i].s.l = l;
@@ -184,12 +192,20 @@ PHP_METHOD(PHPGo__Module, __fun)
184192
free(outs[i].s.s);
185193
break;
186194
default:
187-
free(outs);
188195
php_error(E_ERROR, "Interval error: unknown output type `0x%x`", a->kind);
189196
}
190197
}
191198

192-
free(outs);
199+
out:
200+
if (args) {
201+
efree(args);
202+
}
203+
if (ins) {
204+
efree(ins);
205+
}
206+
if (outs) {
207+
free(outs);
208+
}
193209
}
194210

195211
static void phpgo_add_method(zend_function_entry *fe, php_export *export)
@@ -205,13 +221,25 @@ static void phpgo_add_method(zend_function_entry *fe, php_export *export)
205221
args[argidx+1].name_len = strlen(a->name);
206222
}
207223

208-
fe->fname = estrdup(export->name);
224+
fe->fname = export->name;
209225
fe->handler = ZEND_MN(PHPGo__Module___fun);
210226
fe->arg_info = args;
211227
fe->num_args = export->num_ins;
212228
fe->flags = ZEND_ACC_PUBLIC;
213229
}
214230

231+
void phpgo_module_destroy_class(zend_class_entry *ce)
232+
{
233+
zend_function *f;
234+
for (zend_hash_internal_pointer_reset(&ce->function_table);
235+
zend_hash_get_current_data(&ce->function_table, (void**)&f) == SUCCESS;
236+
zend_hash_move_forward(&ce->function_table)) {
237+
efree((void*)(f->common.arg_info-1));
238+
f->common.arg_info = NULL;
239+
f->common.num_args = 0;
240+
}
241+
}
242+
215243
void phpgo_module_new_instance(zval *ret, phpgo_module *module TSRMLS_DC)
216244
{
217245
zend_class_entry tmpce;
@@ -222,6 +250,11 @@ void phpgo_module_new_instance(zval *ret, phpgo_module *module TSRMLS_DC)
222250
HashPosition pos;
223251
php_export **pexport;
224252
int fidx = -1;
253+
zend_module_entry *prev_module;
254+
255+
// Zend sets some properties on our classes and methods depending on this
256+
prev_module = EG(current_module);
257+
EG(current_module) = &phpgo_module_entry;
225258

226259
spprintf(&class_name, 0, "PHPGo\\Module\\%s_%x_%x", module->name, PHPGO_G(load_counter)++, rand());
227260

@@ -244,6 +277,11 @@ void phpgo_module_new_instance(zval *ret, phpgo_module *module TSRMLS_DC)
244277

245278
intern = (module_intern*)zend_object_store_get_object(ret TSRMLS_CC);
246279
intern->module = module;
280+
281+
efree(class_name);
282+
efree(module_fe);
283+
284+
EG(current_module) = prev_module;
247285
}
248286

249287
void phpgo_module_class_init()

ext/module_class.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@
1818

1919
void phpgo_module_new_instance(zval *ret, phpgo_module *module TSRMLS_DC);
2020
void phpgo_module_class_init();
21+
void phpgo_module_destroy_class(zend_class_entry *ce);
2122

ext/phpgo.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,23 @@ PHP_RINIT_FUNCTION(phpgo)
9797
}
9898
/* }}} */
9999

100+
static int clean_module_class(void *pDest TSRMLS_DC) /* {{{ */
101+
{
102+
zend_class_entry *ce = *(zend_class_entry**)pDest;
103+
if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == phpgo_module_entry.module_number) {
104+
phpgo_module_destroy_class(ce);
105+
return ZEND_HASH_APPLY_REMOVE;
106+
} else {
107+
return ZEND_HASH_APPLY_KEEP;
108+
}
109+
}
110+
/* }}} */
111+
100112
/* {{{ PHP_RSHUTDOWN_FUNCTION
101113
*/
102114
PHP_RSHUTDOWN_FUNCTION(phpgo)
103115
{
116+
zend_hash_apply(EG(class_table), clean_module_class TSRMLS_CC);
104117
return SUCCESS;
105118
}
106119
/* }}} */
@@ -131,7 +144,7 @@ PHP_FUNCTION(phpgo_load)
131144
return;
132145
}
133146

134-
err = phpgo_load(&module, path, name);
147+
err = phpgo_module_load(&module, path, name);
135148
if (err) {
136149
php_error(E_WARNING, "Failed loading %s (%s): %s", path, name, err);
137150
efree(err);

ext/tests/003.phpt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Reflection
55
$module = phpgo_load(__DIR__ . "/fixtures/go/test.so", "test");
66
ReflectionClass::export($module);
77
--EXPECTF--
8-
Class [ <internal> final class PHPGo\Module\test_%s ] {
8+
Class [ <internal:phpgo> final class PHPGo\Module\test_%s ] {
99

1010
- Constants [0] {
1111
}
@@ -20,95 +20,95 @@ Class [ <internal> final class PHPGo\Module\test_%s ] {
2020
}
2121

2222
- Methods [12] {
23-
Method [ <internal> public method add ] {
23+
Method [ <internal:phpgo> public method add ] {
2424

2525
- Parameters [2] {
2626
Parameter #0 [ <required> $int_0 ]
2727
Parameter #1 [ <required> $int_1 ]
2828
}
2929
}
3030

31-
Method [ <internal> public method add32 ] {
31+
Method [ <internal:phpgo> public method add32 ] {
3232

3333
- Parameters [2] {
3434
Parameter #0 [ <required> $int32_0 ]
3535
Parameter #1 [ <required> $int32_1 ]
3636
}
3737
}
3838

39-
Method [ <internal> public method add64 ] {
39+
Method [ <internal:phpgo> public method add64 ] {
4040

4141
- Parameters [2] {
4242
Parameter #0 [ <required> $int64_0 ]
4343
Parameter #1 [ <required> $int64_1 ]
4444
}
4545
}
4646

47-
Method [ <internal> public method add8 ] {
47+
Method [ <internal:phpgo> public method add8 ] {
4848

4949
- Parameters [2] {
5050
Parameter #0 [ <required> $int8_0 ]
5151
Parameter #1 [ <required> $int8_1 ]
5252
}
5353
}
5454

55-
Method [ <internal> public method addf32 ] {
55+
Method [ <internal:phpgo> public method addf32 ] {
5656

5757
- Parameters [2] {
5858
Parameter #0 [ <required> $float32_0 ]
5959
Parameter #1 [ <required> $float32_1 ]
6060
}
6161
}
6262

63-
Method [ <internal> public method addf64 ] {
63+
Method [ <internal:phpgo> public method addf64 ] {
6464

6565
- Parameters [2] {
6666
Parameter #0 [ <required> $float64_0 ]
6767
Parameter #1 [ <required> $float64_1 ]
6868
}
6969
}
7070

71-
Method [ <internal> public method addu ] {
71+
Method [ <internal:phpgo> public method addu ] {
7272

7373
- Parameters [2] {
7474
Parameter #0 [ <required> $uint_0 ]
7575
Parameter #1 [ <required> $uint_1 ]
7676
}
7777
}
7878

79-
Method [ <internal> public method addu32 ] {
79+
Method [ <internal:phpgo> public method addu32 ] {
8080

8181
- Parameters [2] {
8282
Parameter #0 [ <required> $uint32_0 ]
8383
Parameter #1 [ <required> $uint32_1 ]
8484
}
8585
}
8686

87-
Method [ <internal> public method addu64 ] {
87+
Method [ <internal:phpgo> public method addu64 ] {
8888

8989
- Parameters [2] {
9090
Parameter #0 [ <required> $uint64_0 ]
9191
Parameter #1 [ <required> $uint64_1 ]
9292
}
9393
}
9494

95-
Method [ <internal> public method addu8 ] {
95+
Method [ <internal:phpgo> public method addu8 ] {
9696

9797
- Parameters [2] {
9898
Parameter #0 [ <required> $uint8_0 ]
9999
Parameter #1 [ <required> $uint8_1 ]
100100
}
101101
}
102102

103-
Method [ <internal> public method boolAnd ] {
103+
Method [ <internal:phpgo> public method boolAnd ] {
104104

105105
- Parameters [2] {
106106
Parameter #0 [ <required> $bool_0 ]
107107
Parameter #1 [ <required> $bool_1 ]
108108
}
109109
}
110110

111-
Method [ <internal> public method concat ] {
111+
Method [ <internal:phpgo> public method concat ] {
112112

113113
- Parameters [2] {
114114
Parameter #0 [ <required> $string_0 ]

php-go/phpgo.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,14 @@ php_arg_desc * init_php_export_in(php_export * pe, size_t i) {
2222
php_arg_desc * init_php_export_out(php_export * pe, size_t i) {
2323
return &pe->outs[i];
2424
}
25+
26+
void free_php_exports(php_exports * pes) {
27+
int i;
28+
for (i = 0; i < pes->exports; i++) {
29+
php_export * pe = &pes->exports[i];
30+
free(pe->ins);
31+
free(pe->outs);
32+
}
33+
free(pe->exports);
34+
free(pe);
35+
}

0 commit comments

Comments
 (0)