plperl: memory usage stacking
In plperl.c, there are some memory leaks, fixed in the following diff file.
Becuase Perl_eval_pv doesnot release stack, repitition of calling
'plperl_trigger_build_args' makes stack growing up.
The next simple example exhaust memory:(using perl v5.8.0)
while (1) {
AV *av = newAV();
av_undef(av);
}.
I cannot understand the behavior of AV, so, plperl_get_keys, plperl_get_key, and
plperl_get_elem are deleted, and simply implemented by hv_iter* inlined in the
loop.
Tetsuya.
diff plperl.c plperl.c.org
236,237c236
< SV *rv = NULL;
< SV *ret = NULL;
---
SV *rv;
239d237
< char *s;
305,309c303
< ENTER;
< SAVETMPS;
< ret = newSVsv (perl_eval_pv(SvPV(rv, PL_na), TRUE));
< FREETMPS;
< LEAVE;
---
rv = perl_eval_pv(SvPV(rv, PL_na), TRUE);
312d305
< SvREFCNT_dec(rv);
314c307
< return ret;
---
return rv;
320a314,316
char *key;
I32 klen;
SV *val;
325,326c321
< hv_iterinit(hv);
< while (hv_iternext(hv)){
---
while (val = hv_iternextsv(hv, (char**)&key, &klen)){
332a328,371
static
AV*
plperl_get_keys(HV* hv)
{
AV *ret;
SV **svp;
int key_count;
SV *val;
char *key;
I32 klen;
key_count = 0;
ret = newAV();while (val = hv_iternextsv(hv, (char**)&key, &klen)){
av_store(ret, key_count, eval_pv(key, TRUE));
key_count++;
}return ret;
}static
char*
plperl_get_key(AV* keys, int index)
{
SV **svp;
int av_len;av_len = av_len(keys)+1;
if (index < av_len) svp = av_fetch(keys, index, FALSE); else return NULL;
return SvPV(*svp, PL_na);
}static
char*
plperl_get_elem(HV* hash, char* key)
{
SV **svp;
if (hv_exists_ent(hash, eval_pv(key, TRUE), FALSE))
svp = hv_fetch(hash, key, strlen(key), FALSE); else return NULL;return SvPV(*svp, PL_na);
}
363a403
plkeys = plperl_get_keys(hvNew);
382d421
< hv_iterinit(hvNew);
384a424
char *src;
388,389d427
< I32 retlen;
< SV *sv;
391,396c429,430
< sv = hv_iternextsv(hvNew, &platt, &retlen);
< if (sv == NULL)
< elog(FATAL, "plperl: interpreter is probably corrupted");
< plval = SvPV(sv, PL_na);
< if (plval == NULL)
< elog(FATAL, "plperl: interpreter is probably corrupted");
---
platt = plperl_get_key(plkeys, j);
403a438,440
plval = plperl_get_elem(hvNew, platt);
if (plval == NULL)
elog(FATAL, "plperl: interpreter is probably corrupted");
413,428c450,455
< Oid ti;
<
< ti = SPI_gettypeid(tupdesc, modattrs[j]);
< if ( ( (ti != TEXTOID) && (ti != BPCHAROID) && (ti != VARCHAROID) ) && ( (strlen(plval) == 0) || (strcmp(plval, "(null)") == 0) ) )
< {
< modvalues[j] = (Datum) 0;
< modnulls[j] = 'n';
< }
< else
< {
< modvalues[j] = FunctionCall3(&finfo,
< CStringGetDatum(plval),
< ObjectIdGetDatum(typelem),
< Int32GetDatum(tupdesc->attrs[atti]->atttypmod));
< modnulls[j] = ' ';
< }
---
src = plval;
modvalues[j] = FunctionCall3(&finfo,
CStringGetDatum(src),
ObjectIdGetDatum(typelem),
Int32GetDatum(tupdesc->attrs[atti]->atttypmod));
modnulls[j] = ' ';
877d903
< SvREFCNT_dec(svTD);
Please submit as a context diff (made with diff -c) and send it to the
-patches list, rather than -hackers.
cheers
andrew
biz@html.ne.jp wrote:
Show quoted text
In plperl.c, there are some memory leaks, fixed in the following diff file.
Becuase Perl_eval_pv doesnot release stack, repitition of calling
'plperl_trigger_build_args' makes stack growing up.The next simple example exhaust memory:(using perl v5.8.0)
while (1) {
AV *av = newAV();
av_undef(av);
}.
I cannot understand the behavior of AV, so, plperl_get_keys, plperl_get_key, and
plperl_get_elem are deleted, and simply implemented by hv_iter* inlined in the
loop.Tetsuya.
diff plperl.c plperl.c.org236,237c236
< SV *rv = NULL;
< SV *ret = NULL;
---SV *rv;
239d237
< char *s;
305,309c303
< ENTER;
< SAVETMPS;
< ret = newSVsv (perl_eval_pv(SvPV(rv, PL_na), TRUE));
< FREETMPS;
< LEAVE;
---rv = perl_eval_pv(SvPV(rv, PL_na), TRUE);
312d305
< SvREFCNT_dec(rv);
314c307
< return ret;
---return rv;
320a314,316
char *key;
I32 klen;
SV *val;325,326c321
< hv_iterinit(hv);
< while (hv_iternext(hv)){
---while (val = hv_iternextsv(hv, (char**)&key, &klen)){
332a328,371
static
AV*
plperl_get_keys(HV* hv)
{
AV *ret;
SV **svp;
int key_count;
SV *val;
char *key;
I32 klen;
key_count = 0;
ret = newAV();while (val = hv_iternextsv(hv, (char**)&key, &klen)){
av_store(ret, key_count, eval_pv(key, TRUE));
key_count++;
}return ret;
}static
char*
plperl_get_key(AV* keys, int index)
{
SV **svp;
int av_len;av_len = av_len(keys)+1;
if (index < av_len) svp = av_fetch(keys, index, FALSE); else return NULL;
return SvPV(*svp, PL_na);
}static
char*
plperl_get_elem(HV* hash, char* key)
{
SV **svp;
if (hv_exists_ent(hash, eval_pv(key, TRUE), FALSE))
svp = hv_fetch(hash, key, strlen(key), FALSE); else return NULL;return SvPV(*svp, PL_na);
}363a403
plkeys = plperl_get_keys(hvNew);
382d421
< hv_iterinit(hvNew);
384a424char *src;
388,389d427
< I32 retlen;
< SV *sv;
391,396c429,430
< sv = hv_iternextsv(hvNew, &platt, &retlen);
< if (sv == NULL)
< elog(FATAL, "plperl: interpreter is probably corrupted");
< plval = SvPV(sv, PL_na);
< if (plval == NULL)
< elog(FATAL, "plperl: interpreter is probably corrupted");
---platt = plperl_get_key(plkeys, j);
403a438,440
plval = plperl_get_elem(hvNew, platt);
if (plval == NULL)
elog(FATAL, "plperl: interpreter is probably corrupted");413,428c450,455
< Oid ti;
<
< ti = SPI_gettypeid(tupdesc, modattrs[j]);
< if ( ( (ti != TEXTOID) && (ti != BPCHAROID) && (ti != VARCHAROID) ) && ( (strlen(plval) == 0) || (strcmp(plval, "(null)") == 0) ) )
< {
< modvalues[j] = (Datum) 0;
< modnulls[j] = 'n';
< }
< else
< {
< modvalues[j] = FunctionCall3(&finfo,
< CStringGetDatum(plval),
< ObjectIdGetDatum(typelem),
< Int32GetDatum(tupdesc->attrs[atti]->atttypmod));
< modnulls[j] = ' ';
< }
---src = plval;
modvalues[j] = FunctionCall3(&finfo,
CStringGetDatum(src),
ObjectIdGetDatum(typelem),
Int32GetDatum(tupdesc->attrs[atti]->atttypmod));
modnulls[j] = ' ';877d903
< SvREFCNT_dec(svTD);---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
Andrew Dunstan <andrew@dunslane.net> writes:
Please submit as a context diff (made with diff -c) and send it to the
-patches list, rather than -hackers.
It would also help if you'd identify what version the diff is against.
I can't match up any of this with current sources...
regards, tom lane