On 3/25/2020 11:29 PM, S.J. Luo wrote:
Hi,
After further tracing around the sources, I think I've figure out the
root cause of the fault: Tcl interpreter (not Tcl.so, which is
compiled from Tcl.xs) has changed global environment variable of the
process while Perl is not aware of it.
In more detail:
1. Tcl allocated a chunk of memory space to store string 'FOO=bar'
while the code 'set env(FOO) bar' gets executed
2. Tcl modifies the global variable 'environ' (exported by glibc with
type: char**). Then it points to a pointer array with one element
points to the newly allocated string 'FOO=bar'.
3. On exiting of Perl, the destructor of the Tcl interpreter object
gets invoked. The memory chunk with string 'FOO=bar' gets freed by
Tcl. However, the global variable 'environ' still points to the same
location and is still has the element points to the address 'FOO=bar'.
4. Finally Perl thinks the strings pointed by 'environ' was allocated
by itself and calls free() on each element, where one points to string
'FOO=bar', who has already been freed...
To demo the Perl/Tcl behavior, execute
perl -MTcl -e 'Tcl::new->Eval("set env(FOO) bar"); print
"FOO=$ENV{FOO}\n"; system("echo FOO=\$FOO");'
We get the following output before segmentation fault
FOO=
FOO=bar
Here Perl's $ENV{FOO} is still undefined while the true environment of
the process is practically affected because the child process inherits
'FOO=bar'.
Moreover, if we have $ENV{FOO}="bar1" after Eval("set env...."), we
will get segmentation fault on it immediately, before exiting of Perl.
So far I am not able to come out a simple way to get it fixed. I think
either Tcl should not change the environment globally, or there should
be some way to inform Perl that environment variables has been
changed.
SJ
Thank you for investigating this in such great detail.
A Tcl::pTk user opened a ticket observing this issue in the
test suite: https://rt.cpan.org/Ticket/Display.html?id=132278
I had briefly looked online for previous reports of similar issues
for Tcl and Perl, and there were plenty of bug reports and improvements
submitted, often from 20+ years ago. I don't think I came across
this exact issue. But in some cases this kind of issue was deemed
expected behavior, so I wouldn't be surprised if raising this
specific issue with either Perl or Tcl today that they still consider
it to be neither new nor unexpected. For example, a program embedding
Tcl is supposed to do things like use/redefine Tcl_PutEnv()
(see https://www.tcl-lang.org/man/tcl8.6/TclLib/Environment.htm).
But this would appear to assume the program writer is/should be
in control of compiling and packaging everything in their program.
It is not possible to do this when intending for Tcl.pm reuse
existing Tcl or Perl installations, such as from package managers.
So maybe Tcl.pm will have to document this as a known issue.
Or, is there a workaround possible in the meantime?
Christopher A. Chavez