Search code examples
perluwsgidancerperlbrewpsgi

Why a Perlbrew PSGI application with uwsgi_psgi causes "wrong" Perl include paths?


I want to deploy a PSGI based web application by using an uWSGI gateway interface.

To accomplish this I installed Perlbrew locally on my Debian server where no root access is available.

perlbrew init
# close shell and reopen new shell
perlbrew self-install
# close shell and reopen new shell
perlbrew self-upgrade
# close shell and reopen new shell
perlbrew install-patchperl
perlbrew install-cpanm
# close shell and reopen new shell
perlbrew install -j 10 perl-5.26.1
perlbrew lib create perl-5.26.1@main
perlbrew switch perl-5.26.1@main
# close shell and reopen new shell

Then I checked using cpanm -V the Perl environment:

cpanm (App::cpanminus) version 1.7043 (/home/soeren/perl5/perlbrew/bin/cpanm)
perl version 5.026001 (/home/soeren/perl5/perlbrew/perls/perl-5.26.1/bin/perl)

  %Config:
    archname=x86_64-linux
    installsitelib=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/site_perl/5.26.1
    installsitebin=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/bin
    installman1dir=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/man/man1
    installman3dir=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/man/man3
    sitearchexp=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/site_perl/5.26.1/x86_64-linux
    sitelibexp=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/site_perl/5.26.1
    archlibexp=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1/x86_64-linux
    privlibexp=/home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1
  %ENV:
    PERL5LIB=/home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5
    PERLBREW_HOME=/home/soeren/.perlbrew
    PERLBREW_LIB=main
    PERLBREW_MANPATH=/home/soeren/.perlbrew/libs/perl-5.26.1@main/man:/home/soeren/perl5/perlbrew/perls/perl-5.26.1/man
    PERLBREW_PATH=/home/soeren/.perlbrew/libs/perl-5.26.1@main/bin:/home/soeren/perl5/perlbrew/bin:/home/soeren/perl5/perlbrew/perls/perl-5.26.1/bin
    PERLBREW_PERL=perl-5.26.1
    PERLBREW_ROOT=/home/soeren/perl5/perlbrew
    PERLBREW_SHELLRC_VERSION=0.82
    PERLBREW_VERSION=0.82
    PERL_LOCAL_LIB_ROOT=/home/soeren/.perlbrew/libs/perl-5.26.1@main
    PERL_MB_OPT=--install_base /home/soeren/.perlbrew/libs/perl-5.26.1@main
    PERL_MM_OPT=INSTALL_BASE=/home/soeren/.perlbrew/libs/perl-5.26.1@main
  @INC:
    FatPacked::93953009226544=HASH(0x557323bd9330)
    /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/x86_64-linux
    /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5
    /home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/site_perl/5.26.1/x86_64-linux
    /home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/site_perl/5.26.1
    /home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1/x86_64-linux
    /home/soeren/perl5/perlbrew/perls/perl-5.26.1/lib/5.26.1

Everything looks good so I installed Dancer2 as the web framework of choice and successfully launched a skeleton test application:

dancer2 gen --application DemoApp
cd ./DemoApp
plackup ./bin/app.psgi

The Plack-internal HTTP web server has started and was ready to serve the application.

Again, so far so good. But I wanted to go with uWSGI instead of having yet another fully fledged web server in the service chain.

So I installed uwsgi-plugin-psgi which automatically comes with uwsgi-core:

apt install uwsgi-plugin-psgi

Now I wanted to start the uWSGI gateway interface...:

uwsgi_psgi --uwsgi-socket 127.0.0.1:5999 --psgi /home/soeren/DemoApp/bin/app.psgi

...and the application has crashed:

[uwsgi] implicit plugin requested psgi
*** Starting uWSGI 2.0.14-debian (64bit) on [Fri Feb  9 10:41:20 2018] ***
compiled with version: 6.2.1 20161124 on 07 December 2016 16:14:59
os: Linux-4.9.0-5-amd64 #1 SMP Debian 4.9.65-3+deb9u2 (2018-01-04)
nodename: skde-deu-02.sklink.de
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 8
current working directory: /home/soeren/DemoApp
detected binary path: /usr/bin/uwsgi-core
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 256817
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address 127.0.0.1:5999 fd 3
initialized Perl 5.24.1 main interpreter at 0x557337c6fd40
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 72768 bytes (71 KB) for 1 cores
*** Operational MODE: single process ***
Error while loading /home/soeren/DemoApp/bin/app.psgi: Can't locate WWW/Form/UrlEncoded.pm in @INC (you may need to install the WWW::Form::UrlEncoded module) (@INC contains: /home/soeren/DemoApp/bin/../lib /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/5.24.1/x86_64-linux-gnu-thread-multi /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/5.24.1 /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/x86_64-linux-gnu-thread-multi /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.24.1 /usr/local/share/perl/5.24.1 /usr/lib/x86_64-linux-gnu/perl5/5.24 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.24 /usr/share/perl/5.24 /usr/local/lib/site_perl) at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/HTTP/Entity/Parser/UrlEncoded.pm line 5.
BEGIN failed--compilation aborted at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/HTTP/Entity/Parser/UrlEncoded.pm line 5.
Compilation failed in require at /usr/share/perl/5.24/Module/Load.pm line 77.
Can't locate HTTP/Entity/Parser/UrlEncoded in @INC (@INC contains: /home/soeren/DemoApp/bin/../lib /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/5.24.1/x86_64-linux-gnu-thread-multi /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/5.24.1 /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/x86_64-linux-gnu-thread-multi /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.24.1 /usr/local/share/perl/5.24.1 /usr/lib/x86_64-linux-gnu/perl5/5.24 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.24 /usr/share/perl/5.24 /usr/local/lib/site_perl) at /usr/share/perl/5.24/Module/Load.pm line 77.
Compilation failed in require at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Plack/Request.pm line 17.
BEGIN failed--compilation aborted at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Plack/Request.pm line 17.
Compilation failed in require at /usr/share/perl/5.24/parent.pm line 16.
BEGIN failed--compilation aborted at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Dancer2/Core/Request.pm line 6.
Compilation failed in require at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Dancer2/Core/App.pm line 29.
BEGIN failed--compilation aborted at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Dancer2/Core/App.pm line 29.
Compilation failed in require at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Dancer2.pm line 11.
BEGIN failed--compilation aborted at /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/Dancer2.pm line 11.
Compilation failed in require at /home/soeren/DemoApp/bin/../lib/DemoApp.pm line 2.
BEGIN failed--compilation aborted at /home/soeren/DemoApp/bin/../lib/DemoApp.pm line 2.
Compilation failed in require at /home/soeren/DemoApp/bin/app.psgi line 10.
BEGIN failed--compilation aborted at /home/soeren/DemoApp/bin/app.psgi line 10.
unable to find PSGI function entry point.
*** no app loaded. going in full dynamic mode ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 9769, cores: 1)

The fist thing that I see was the architecture. While the other (cpnam and plackup) programs using "x86_64-linux" architecture, only uWSGI is using "x86_64-linux-gnu-thread-multi" instead.

Well Perl's architecture folder for "x86_64-linux-gnu-thread-multi" is available but does not contain any modules. Most modules are installed in the "root library path" and "x86_64-linux" architecture folder.

/home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5
/home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/x86_64-linux

I tried to work around this by using the uwsgi_psgi command line switch --perl-local-lib but had no luck:

uwsgi_psgi --uwsgi-socket 127.0.0.1:5999 --psgi /home/soeren/DemoApp/bin/app.psgi --perl-local-lib /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5
uwsgi_psgi --uwsgi-socket 127.0.0.1:5999 --psgi /home/soeren/DemoApp/bin/app.psgi --perl-local-lib /home/soeren/.perlbrew/libs/perl-5.26.1@main/lib/perl5/x86_64-linux

I also have messed around with different uWSGI operation modes (single process, prefork, threaded), but also no luck.

Why is uWSGI modifying the include path and how do I either start uWSGI so it works like with the other programs or install the modules for that architecture in addition?


Solution

  • I found a solution, thanks to @simbabque.

    My issue was that I was using the system native uwsgi_psgi, which was compiled with the system Perl installation and was not compatible with my local Perlbrew installation.

    This mailing list thread suggest to recompile uwsgi within the Perlbrew scope to be able to work (only) with the local Perlbrew installation.

    So by doing the following compile I get managed to start the Perl application:

    curl http://uwsgi.it/install | bash -s psgi /home/soeren/perl5/perlbrew/bin/uwsgi
    

    However the above shown command is not the best way since it lacks all further important compile switches (e.g. pcre, jit).

    I will improve this answer over time with the further compile switches.