Segmentation fault in XS.so
rodolfojcj opened this issue · comments
Hello.
I'm facing an intermittent issue in a web site of mine, which runs in Ubuntu 20.04, mainly with Apache 2.4.41, Perl 5.30.0 and mod_perl 2.0.11.
After a lot of debugging I found a minimal way to reproduce it, according to the following details.
Setup the server environment
This assumes a fresh Ubuntu 20.04 installation for an x86_64 CPU.
-
Run these commands:
apt-get install apache2
apt-get install libapache2-mod-perl2
apt-get install libcrypt-jwt-perl # this one installs these dependencies: libcpanel-json-xs-perl{a} libcryptx-perl{a} and libjson-maybexs-perl{a}
mkdir /var/perl_code
-
Create the file /etc/apache2/sites-available/buggy-site.com.conf with this content:
<VirtualHost *:80> ServerName buggy-site.com DocumentRoot /var/perl_code ErrorLog ${APACHE_LOG_DIR}/buggy-site-error.log CustomLog ${APACHE_LOG_DIR}/buggy-site-access.log combined <Directory "/var/perl_code"> Options ExecCGI DirectoryIndex index.pl <IfVersion >= 2.3> Require all granted </IfVersion> AllowOverride All <Files *.pl> SetHandler perl-script Options +ExecCGI PerlResponseHandler ModPerl::Registry PerlSendHeader On </Files> </Directory> </VirtualHost>
-
Create the file /var/perl_code/index.pl with this content:
#!/usr/bin/perl -w use strict; use warnings; # this single line is enough to trigger the segmentation fault use Crypt::JWT; print 'Content-Type: ' . 'application/json' . "\r\n"; print 'Content-Disposition: attachment;filename="' . 'attached_file.json' . "\"\r\n"; print "Accept-Ranges: bytes\r\n"; my $response_content = '{"responses":[{"code":"200","message":"OK","key":""}],"data":{"found":1}}'; print 'Content-Length: ' . length( $response_content ) . "\r\n"; print "\r\n"; print $response_content;
-
Enable the virtual host site with these commands:
a2ensite buggy-site.com.conf
systemctl restart apache2.service
Setup the client environment
I assume the client has a terminal to run commands, with the wget
installed to open URLs.
To emulate a public we site, edit its /etc/hosts file to add a line that associates the IP address of the server with the sample domain name of the configured web site. In my example, that line would be like this:
192.168.1.100 buggy-site.com
An alternative to this is to have a DNS record that correctly associates the server IP address with the domain name of the sample web site.
Use the web site
From this moment on, I will mention two sides in turns, one for the server and other for the client.
-
In the client, I'm using this command to access the configured web site whenever I want:
wget --server-response --output-document=- http://buggy-site.com
No matter how many times I execute that wget
command, no errors will happen (or at least I did not observe hints about it). I presume that this is because the Apache web server is running multiple processes, given the MPM "prefork", "event" or "worker" modules that are generally used. Also, in my web site having such multiple processes increased the difficulty to debug and isolate the error.
-
In the server, open a terminal to monitor the Apache and operating system log files, for example with this command:
tail -f /var/log/apache2/*.log /var/log/syslog
-
In the server, stop the Apache web server with this command:
systemctl stop apache2.service
-
In the server, start the Apache web server in debug mode with these commands:
source /etc/apache2/envvars
apache2 -X
That is convenient to run the Apache web server with a single process.
- In the client, run the
wget
command previously given to access the web site. That command finishes successfully, getting the expected content from the server. At this moment the server works normally, without showing symptoms of an error.
Trigger the error
In the server, go to the terminal that keeps running the apache2 -X
command and stop it by pressing the "Ctrl + C" keys sequence.
After doing that, these things will happen:
-
The terminal where the
apache2 -X
was running will show this mesage:Segmentation fault (core dumped)
-
The /var/log/syslog file will show a couple of lines like these:
May 20 15:18:44 localhost kernel: [ 1435.562727] apache2[6398]: segfault at 8 ip 00007f57c06b7f47 sp 00007ffd0bacf8e8 error 4 in XS.so[7f57c06b7000+f000] May 20 15:18:44 localhost kernel: [ 1435.562743] Code: 1f 40 00 f3 0f 1e fa 48 63 15 dd 30 01 00 48 8b 87 78 0b 00 00 48 83 6f 78 04 48 8b 04 d0 48 8b 70 30 48 c7 40 30 00 00 00 00 <8b> 56 08 83 fa 01 76 11 83 ea 01 89 56 08 c3 66 2e 0f 1f 84 00 00
I presume that the mentioned XS.so file in the first line corresponds to the /usr/lib/x86_64-linux-gnu/perl5/5.30/auto/Cpanel/JSON/XS/XS.so file, which is probably opened as part of the following sequence of opened files:
/usr/local/share/perl/5.30.0/Crypt/JWT.pm
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/Crypt/Misc.pm
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/CryptX.pm
/usr/lib/x86_64-linux-gnu/perl5/5.30/Cpanel/JSON/XS.pm
/usr/lib/x86_64-linux-gnu/perl5/5.30/auto/Cpanel/JSON/XS/XS.so
- A core dump file will appear under the /var/crash/ directory.
My observations
-
The system has these packages installed:
libcrypt-jwt-perl (version 0.026-1) libcryptx-perl (version 0.067-1) libcpanel-json-xs-perl (version 4.19-1build1) libjson-maybexs-perl (version 1.004000-1)
-
The Perl module Crypt::JWT depends on CryptX, which uses a JSON::XS implementation or JSON::PP, preferring Cpanel::JSON::XS when selecting one of them. This is evident from this code fragment taken from the /usr/local/lib/x86_64-linux-gnu/perl/5.30.0/CryptX.pm file in the server:
... our $VERSION = '0.069'; ... BEGIN { if (eval { require Cpanel::JSON::XS }) { Cpanel::JSON::XS->import(qw(encode_json decode_json)); $has_json = 1; } elsif (eval { require JSON::XS }) { JSON::XS->import(qw(encode_json decode_json)); $has_json = 2; } elsif (eval { require JSON::PP }) { JSON::PP->import(qw(encode_json decode_json)); $has_json = 3; } else { $has_json = 0; } }
-
Given that first preference that CryptX has, I think that the segmentation fault is caused by some bug in the Cpanel::JSON::XS implementation, however I could be wrong, in which case I will need to create an issue for that CryptX module.
A workaround
Installing JSON::XS and removing Cpanel::JSON::XS brings these two things:
- Stops the segmentation fault from happening when executing the
apache2 -X
command. - Stops the intermittent issue I faced with the web site of mine.
To do that, these are the commands to execute in the server:
aptitude install libjson-xs-perl
aptitude remove libcpanel-json-xs-perl
What to do?
- If possible I would like to have this issue confirmed, solved and with a fix published for Ubuntu 20.04.
- Also, I would like to keep using the Cpanel::JSON::XS module because its documentation says that it "...has proper ithreads support..." and because it is frequently updated and enhanced.
In case there is something that I could help with, it would be my pleasure.
Thanks in advance for your time and attention.
To verify if the problem is caused by outdated Perl modules in Ubuntu 20.04, I tried with uninstalling the relevant operating system packages and installing the recent ones available in CPAN, however I still get the "segmentation fault" error previously described.
These are the commands I executed this time:
aptitude remove libcpanel-json-xs-perl
aptitude remove libjson-xs-perl
# I chose the option that removed the other packages that depended on them
dpkg -l | grep -i perl | grep -i json
# (returns an empty output)
dpkg -l | grep -i perl | grep -i crypt
# (returns an empty output)
apt-get install cpanminus
apt-get install make
apt-get install gcc
cpanm Cpanel::JSON::XS
# (this successfully installs Cpanel::JSON::XS version 4.26)
cpanm Crypt::JWT
# (this successfully installs Crypt-JWT version 0.033 with its dependencies JSON version 4.03 and CryptX version 0.072)
apache2 -X
# (after the wget request, typed Ctrl+C to stop the web server)
Continuing with my previous comment, I tried with manually removing the Cpanel::JSON::XS that I installed from CPAN, observing that again this stops the "segmentation fault" from happening.
This is the executed command, showing the files that were removed:
cpanm --uninstall Cpanel::JSON::XS
Cpanel::JSON::XS contains the following files:
/usr/local/bin/cpanel_json_xs
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/Cpanel/JSON/XS.pm
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/Cpanel/JSON/XS/Boolean.pm
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/Cpanel/JSON/XS/Type.pm
/usr/local/lib/x86_64-linux-gnu/perl/5.30.0/auto/Cpanel/JSON/XS/XS.so
/usr/local/man/man1/cpanel_json_xs.1p
/usr/local/man/man3/Cpanel::JSON::XS.3pm
/usr/local/man/man3/Cpanel::JSON::XS::Boolean.3pm
/usr/local/man/man3/Cpanel::JSON::XS::Type.3pm
With Ubuntu 21.04 (Hirsute Hippo) the "segmentation fault" also happens, in a similar way to that described for Ubuntu 20.04.
The difference is that I needed to manually install the libcpanel-json-xs-perl
package, because it is no longer a dependency for libcrypt-jwt-perl
, which now depends on the libjson-perl
package, which in turn ends installing the now preferred libjson-xs-perl
package.
With the older Ubuntu 18.04 (Bionic Beaver) the "segmentation fault" error does not happen.
I found these differences in this case:
-
The package
libcrypt-jwt-perl
does not exist in that distribution. -
I manually installed the
libcpanel-json-xs-perl
andlibjson-xs-perl
with these commands:apt-get install libcpanel-json-xs-perl # this installed version 3.0239-1 apt-get install libjson-xs-perl # this installed version 3.040-1
-
To use the
cpanm
command, I previously executed these commands:apt-get install cpanminus apt-get install make apt-get install gcc
-
From CPAN, I installed Crypt::JWT with this command:
cpanm Crypt::JWT # this installed Crypt-JWT version 0.033 and its dependencies CryptX version 0.072 and JSON version 4.03
Thanks for the simple testcase, the rest is all irrelevant
Sorry, the testcase is still too baroque. I don't have a mod_perl with a threaded perl.
encode and decode with threads do work fine in this lib, but maybe mod_perl has problems with threaded DESTRUCT?
Cannot you come up with a simple testcase, similar to t/125_shared_boolean.t
?
Crypt::JWT only uses JSON, not JSON::MaybeXS or this module.
Hello, thanks for the feedback.
I would need to investigate about a possible problem with mod_perl and perl threads.
Were you able to reproduce the segmentation fault by following the steps I described?
Crypt:JWT uses CryptX, which in turn uses either Cpanel::JSON::XS as its preferred JSON::XS implementation, as mentioned under the "My observations" section in the initial comment for this issue.
I will review the approach in t/125_shared_boolean.t
and will come with details if I find something.
Regards.
No, I couldn't repro it
I suspect it will be fixed in 4.28 with the new improvements in END and DESTROY.
Please re-open if 4.28 didn't fix it.