Re: BUG #17946: LC_MONETARY & DO LANGUAGE plperl - BUG - Mailing list pgsql-hackers

From Joe Conway
Subject Re: BUG #17946: LC_MONETARY & DO LANGUAGE plperl - BUG
Date
Msg-id 4934c037-aac0-b64b-1b67-b52a32076b9b@joeconway.com
Whole thread Raw
In response to Re: BUG #17946: LC_MONETARY & DO LANGUAGE plperl - BUG  (Heikki Linnakangas <hlinnaka@iki.fi>)
Responses Re: BUG #17946: LC_MONETARY & DO LANGUAGE plperl - BUG
List pgsql-hackers
On 8/15/23 10:40, Heikki Linnakangas wrote:
> On 01/08/2023 16:48, Joe Conway wrote:
>> Any further comments on the posted patch[1]? I would like to apply/push
>> this prior to the beta and minor releases next week.
> 
> I'm not sure about the placement of the uselocale() calls. In
> plperl_spi_exec(), for example, I think we should switch to the global
> locale right after the check_spi_usage_allowed() call. Otherwise, if an
> error happens in BeginInternalSubTransaction() or in pg_verifymbstr(),
> the error would be processed with the perl locale. Maybe that's
> harmless, error processing hardly cares about LC_MONETARY, but seems
> wrong in principle.

I guess you could probably argue that we should flip this around, and 
only enter the perl locale when calling into libperl, and exit the perl 
locale every time we reemerge under plperl.c control. That seems pretty 
drastic and potentially messy though.

> Hmm, come to think of it, if BeginInternalSubTransaction() throws an
> error, we just jump out of the perl interpreter? That doesn't seem cool.
> But that's not new with this patch.

Hmm, true enough I guess.

> If I'm reading correctly, compile_plperl_function() calls
> select_perl_context(), which calls plperl_trusted_init(), which calls
> uselocale(). So it leaves locale set to the perl locale. Who sets it back?

No one does it seems, at least not currently

> How about adding a small wrapper around eval_pl() that sets and unsets
> the locale(), just when we enter the interpreter? It's easier to see
> that we are doing the calls in right places, if we make them as close as
> possible to entering/exiting the interpreter. Are there other functions
> in addition to eval_pl() that need to be called with the perl locale?

I can see that as a better strategy, but "other functions in addition to 
eval_pv()" (I assume you mean eval_pv rather than eval_pl) is a tricky 
one to answer.

I ran the attached script like so (from cwd src/pl/plperl) like so:
```
symbols-used.sh /lib/x86_64-linux-gnu/libperl.so.5.34 plperl.so
```
and get a fairly long list of exported libperl functions that get linked 
into plperl.so:

```
Matched symbols:
boot_DynaLoader
perl_alloc
Perl_av_extend
Perl_av_fetch
Perl_av_len
Perl_av_push
*Perl_call_list
*Perl_call_pv
*Perl_call_sv
perl_construct
Perl_croak
Perl_croak_nocontext
Perl_croak_sv
Perl_croak_xs_usage
Perl_die
*Perl_eval_pv
Perl_free_tmps
Perl_get_sv
Perl_gv_add_by_type
Perl_gv_stashpv
Perl_hv_clear
Perl_hv_common
Perl_hv_common_key_len
Perl_hv_iterinit
Perl_hv_iternext
Perl_hv_iternext_flags
Perl_hv_iternextsv
Perl_hv_ksplit
Perl_looks_like_number
Perl_markstack_grow
Perl_mg_get
Perl_newRV
Perl_newRV_noinc
Perl_newSV
Perl_newSViv
Perl_newSVpv
Perl_newSVpvn
Perl_newSVpvn_flags
Perl_newSVsv
Perl_newSVsv_flags
Perl_newSV_type
Perl_newSVuv
Perl_newXS
Perl_newXS_flags
*perl_parse
Perl_pop_scope
Perl_push_scope
*perl_run
Perl_save_item
Perl_savetmps
Perl_stack_grow
Perl_sv_2bool
Perl_sv_2bool_flags
Perl_sv_2iv
Perl_sv_2iv_flags
Perl_sv_2mortal
Perl_sv_2pv
Perl_sv_2pvbyte
Perl_sv_2pvbyte_flags
Perl_sv_2pv_flags
Perl_sv_2pvutf8
Perl_sv_2pvutf8_flags
Perl_sv_bless
Perl_sv_free
Perl_sv_free2
Perl_sv_isa
Perl_sv_newmortal
Perl_sv_setiv
Perl_sv_setiv_mg
Perl_sv_setsv
Perl_sv_setsv_flags
Perl_sys_init
Perl_sys_init3
Perl_xs_boot_epilog
Perl_xs_handshake
```

I marked the ones that look like perhaps we should care about in the 
above list with an asterisk:

*Perl_call_list
*Perl_call_pv
*Perl_call_sv
*Perl_eval_pv
*perl_run

but perhaps there are others?

>> /*
>>  * plperl_xact_callback --- cleanup at main-transaction end.
>>  */
>> static void
>> plperl_xact_callback(XactEvent event, void *arg)
>> {
>>     /* ensure global locale is the current locale */
>>     if (uselocale((locale_t) 0) != LC_GLOBAL_LOCALE)
>>         perl_locale_obj = uselocale(LC_GLOBAL_LOCALE);
>> }
> 
> So the assumption is that the if current locale is not LC_GLOBAL_LOCALE,
> then it was the perl locale. Seems true today, but this could confusion
> if anything else calls uselocale(). In particular, if another PL
> implementation copies this, and you use plperl and the other PL at the
> same time, they would get mixed up. I think we need another "bool
> perl_locale_obj_in_use" variable to track explicitly whether the perl
> locale is currently active.

Or perhaps don't assume that we want the global locale and swap between 
pg_locale_obj (whatever it is) and perl_locale_obj?

> If we are careful to put the uselocale() calls in the right places so
> that we never ereport() while in perl locale, this callback isn't
> needed. Maybe it's still a good idea, though, to be extra sure that
> things get reset to a sane state if something unexpected happens.

I feel more comfortable that we have a "belt and suspenders" method to 
restore the locale that was in use by Postgres before entering perl.

> If multiple interpreters are used, is the single perl_locale_obj
> variable still enough? Each interpreter can have their own locale I believe.

So in other words plperl and plperlu both used in the same query? I 
don't see how we could get from one to the other without going through 
the outer "postgres" locale first. Or are you thinking something else?

> PS. please pgindent

ok

-- 
Joe Conway
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

Attachment

pgsql-hackers by date:

Previous
From: Yugo NAGATA
Date:
Subject: Re: Incremental View Maintenance, take 2
Next
From: Yugo NAGATA
Date:
Subject: Re: Incremental View Maintenance, take 2