[Cascavel-pm] mod_perl

breno breno em rio.pm.org
Sábado Dezembro 13 07:12:15 PST 2014


Oi Kleber,

desculpa não ter respondido antes, só vi o email agora :(

Ainda está com problemas para carregar funções? O mod_perl é uma ferramenta
poderosa mas um tanto confusa mesmo - por essas e outras que o
desenvolvimento Perl moderno para web foge dessas implementações e prefere
soluções como PSGI.

Pela sua mensagem, parece que o mod_perl está tendo dificuldades em
encontrar a função "grava_conf" criada pelo seu código. Estou supondo que
ela é criada e importada ao carregar o arquivo "c:\payback\dosbox.plx", mas
é só achismo meu - me corrija se estiver errado!

Se é esse o caso, o cache do mod_perl pode estar se perdendo. Ele compila
uma vez, grava no namespace ModPerl::ROOT::ModPerl::Registry:::blablabla, e
esquece. Na hora que você executa em outro script, ele ve que o arquivo já
está compilado em memória e pula, mas como o seu arquivo atual foi gravado
em *outro* namespace do mod_perl, ele não acha a função.

Uma solução rápida para você é descobrir em que módulo a função
"grava_conf" é definida e chamar ela com o full namespace em vez de apenas
como "grava_conf()". Por exemplo, suponha que ela tenha sido definida no
módulo Payback::Utils:

---------8<---------
package Payback::Utils;
use strict;
use warnings;

sub grava_conf {
    ...
}

1;
--------->8---------

Daí, nos lugares onde você usa, em vez de dizer:


require 'c:\\payback\\dosbox.plx';
grava_conf($conf,$prog);


Você tem que dizer:

require 'c:\\payback\\dosbox.plx';
Payback::Utils::grava_conf($conf,$prog);

Isso deve resolver o seu problema de função não encontrada dentro do
mod_perl (espero!)


Dito isso, acho importante citar que, na maioria dos casos, ter "require"
escrito assim não é uma boa prática hoje em dia. Há vários motivos para
isso (além do problema que você já está experimentando): a dependência via
"require" é avaliada durante o tempo de execução, não de compilação,
deixando a execução do seu programa potencialmente mais lenta; o "require"
exige o caminho do arquivo no sistema de arquivos em vez de abstrair isso
pra você e acaba deixando o seu código menos portátil - imagine ter que
rodar seu código Windows em um Linux, você vai ter que mudar o "c:\" e as
barras em tudo! Mesmo no Windows, imagine ter que botar seu programa em
outro diretório? Finalmente, o require estimula carregar scripts ".pl"
quando a boa prática de hoje sugere que você separe seu programa
logicamente em módulos, facilitando a reutilização de código, a
identificação de erros e a manutenção do seu programa. Ou seja, em vez de
'c:\\payback\\dosbox.plx',você teria um arquivo (por exemplo)
"lib/Dosbox.pm" com:

---------8<---------
package Dosbox;
use strict;
use warnings;

# funcoes do dosbox.plx

1;
--------->8---------

e em vez de chamar como:

 require 'c:\\payback\\dosbox.plx';

você colocaria um:

use Dosbox;

no topo do seu código.

Idealmente, o código dentro do script "c:\\payback\dosbox.plx" seria
refatorado em módulo(s) com namespace(s) significativo(s). Mesmo deixar
tudo desse arquivo junto em um grande "Dosbox.pm" já seria potencialmente
benéfico. Se o script de antes não apenas definia funções mas também
executava algum código, declarava variáveis, etc, você pode iniciar o
refactoring colocando todo o código dentro de uma grande sub e ir separando
aos poucos. Isso é particularmente importante se você tem muitas variáveis
"my" e está em ambiente mod_perl, já que o comportamento do mod_perl pode
tornar o conteúdo delas inesperado.

Espero ter ajudado! E desculpe novamente pela demora.

[]s

-b



On Sun, Nov 30, 2014 at 5:33 PM, kleber <payback em oi.com.br> wrote:
>
> Olá Srs  ,
>
> Instalei o mod_perl no meu computador sendo que ao iniciá-lo recebo a
> seguinte mensagem :
>
> [Sun Nov 30 09:29:28 2014] [notice] Apache/2.2.22 (Win32) PHP/5.2.8
> mod_apreq2-20090110/2.8.0 mod_perl/2.0.7 Perl/v5.16.3 configured --
> resuming normal operations
>
> Utilizei a seguinte configuração no apache :
>
> PerlModule ModPerl::RegistryBB
> <Files ~ "\.plx$">
>  SetHandler perl-script
>  PerlResponseHandler ModPerl::RegistryBB::handler
>  PerlOptions +ParseHeaders
>  Options -Indexes MultiViews FollowSymLinks +ExecCGI
>  PerlSendHeader On
>  Order allow,deny
>  Allow from all
> </Files>
>
> Consigo executar vários scripts em mod_perl porém estou tendo problema com
> scripts que tem as instruções :
>
>                   require 'c:\\payback\\dosbox.plx';
>                   grava_conf($conf,$prog);
>
> Quando executo o script com esta característica recebo a seguinte mensagem
> de erro :
>
> [error]Undefined subroutine &ModPerl::ROOT::ModPerl::
> RegistryBB::C_3a_Payback_Contabil_Operacao_Fluxo_Formulario_2eplx::grava_conf
> called at C:/Payback/Formulario.plx line 47.
>
> Nota - Em ambiente cgi ( sem mod_perl ) todos os scripts são executados
> normalmente ( sem problemas ).
>
> Pesquisando na internet encontrei o seguinte texto no perl.apache.org : (
> http://perl.apache.org/docs/1.0/guide/porting.html  - See Names
> collisions with Modules and libs.) :
>
> There are three solutions for this:
>
> .Solution 1
>
> The first two faulty scenarios can be solved by placing your library
> modules in a subdirectory structure so that they have different path
> prefixes.
> The file system layout will be something like:
>  ./tool1/Tool1/Foo.pm
>  ./tool1/tool1.pl
>  ./tool2/Tool2/Foo.pm
>  ./tool2/tool2.pl
>
> And modify the scripts:
>  use Tool1::Foo;
>  use Tool2::Foo;
>
> For require() (scenario number 2) use the following:
>  ./tool1/tool1-lib/config.pl
>  ./tool1/tool1.pl
>  ./tool2/tool2-lib/config.pl
>  ./tool2/tool2.pl
>
> And each script contains respectively:
>  use lib qw(.);
>  require "tool1-lib/config.pl";
>
>  use lib qw(.);
>  require "tool2-lib/config.pl";
>
> This solution isn't good, since while it might work for you now, if you
> add another script that wants to use the same module or config.pl file,
> it would fail as we saw in the third scenario.
>
> Let's see some better solutions.
>
> .Solution 2
>
> Another option is to use a full path to the script, so it will be used as
> a key in %INC;
>  require "/full/path/to/the/config.pl";
>
> This solution solves the problem of the first two scenarios. I was
> surprised that it worked for the third scenario as well!
>
> With this solution you lose some portability.
> If you move the tool around in the file system you will have to change the
> base directory or write some additional script that will automatically
> update the hardcoded path after it was moved.
> Of course you will have to remember to invoke it.
>
> .Solution 3
>
> Make sure you read all of this solution.
>
> Declare a package name in the required files! It should be unique in
> relation to the rest of the package names you use. %INC will then use the
> unique package name for the key.
> It's a good idea to use at least two-level package names for your private
> modules, e.g. MyProject::Carp and not Carp, since the latter will collide
> with an existing standard package.
> Even though a package may not exist in the standard distribution now, a
> package may come along in a later distribution which collides with a name
> you've chosen.
> Using a two part package name will help avoid this problem.
>
> Even a better approach is to use three level naming, like
> CompanyName::ProjectName::Module, which is most unlikely to have
> conflicts with later Perl releases.
> Foresee problems like this and save yourself future trouble.
>
> What are the implications of package declaration?
>
> Without package declarations, it is very convenient to use() or require()
> files because all the variables and subroutines are part of the main::
> package.
> Any of them can be used as if they are part of the main script. With
> package declarations things are more awkward.
> You have to use the Package::function() method to call a subroutine from
> Package and to access a global variable $foo inside the same package you
> have to write $Package::foo.
>
> Lexically defined variables, those declared with my () inside Package will
> be inaccessible from outside the package.
>
> You can leave your scripts unchanged if you import the names of the global
> variables and subroutines into the namespace of package main:: like this:
> use Module qw(:mysubs sub_b $var1 :myvars);
>
> You can export both subroutines and global variables. Note however that
> this method has the disadvantage of consuming more memory for the current
> process.
>
> See perldoc Exporter for information about exporting other variables and
> symbols.
>
> This completely covers the third scenario. When you use different module
> names in package declarations, as explained above, you cover the first two
> as well.
>
> Comentário - Estas alternativas inviabiliza a utilização do mod_perl em
> meu ambiente sistêmico ( existem vários scripts que utilizam a instrução
> require ) e
> não seria sensato ter que multiplicá-los para individualizar nomes.
>
> ____________________________________________________________
> ________________________________________
>
> Localizei também este texto na internet e não entendi ( meu conhecimento
> em perl é limitado )
>
> Code Caching Effects ( http://www.informit.com/
> articles/article.aspx?p=23010&seqNum=4  )
>
> Recall that mod_perl caches compiled scripts.
> This helps it run scripts faster, but what happens if you change a script?
> Does mod_perl continue to execute
> the cached version? Nope. Apache::Registry keeps track of the scripts that
> it has run and checks the modification date of the original file when a
> script is requested again.
> If the date has changed, it recompiles the script and the new version is
> used instead.
> You can verify this for yourself. Request a script, and then change it and
> click the Reload button in your browser.
> You should see the changed output.Then change the script back and click
> Reload again.You should see the original output.That's what you expect and
> want to happen.2
>
> However, this behavior doesn't apply to modules pulled into your script
> via use or require.
> If you change those files, the changes won't be noticed until you restart
> the server.
> Another workaround for this problem is to use the Apache::StatINC module,
> which forces Apache to check the last modification time even for modules
> referenced from use or require statements.
> This is a technique best used on a development server, because it slows
> down Apache. Run perldoc Apache::StatINC from the command line for more
> information.
>
> Script caching also is responsible for another mysterious problem.
> If you use or require a library file, that file's code is pulled in to
> your script, compiled, and cached, as usual.
> If the file doesn't contain a package declaration to specify a namespace,
> however, the code goes into your script's own namespace.
> This is main when you run scripts in standalone mode, but scripts run in
> their own unique namespace under mod_perl.
> If your script is called script.pl, for example, the namespace might be
> &Apache::ROOT::cgi_2dperl::script_2epl.
> Normally, having unique namespaces per script is a good thing, because it
> helps keep scripts that are run under a given httpd child from colliding
> with each other in the main namespace.
> But it causes a problem for unpackaged library code. Here's why: Suppose
> you run your script script.pl that uses a library file MyLib.pm
> containing a function lib_func(). script.pl will execute properly.
> Now suppose you have a second script, script2.pl, that wants to use
> MyLib.pm, too.When the second script, executes, mod_perl, sees the use or
> require line for the library file,
> notices that the file has already been processed and cached, and doesn't
> bother to recompile it.Then when script2.pl calls lib_func() from the
> library file, an error occurs:
>
> [error] Undefined subroutine
> &Apache::ROOT::cgi_2dperl::script2_2epl::lib_func called
>
> This happens because functions in the library file have been compiled, but
> they're in the namespace for script.pl, not script2.pl.To fix this
> problem,
> make sure the library file includes a package declaration, and then invoke
> its functions using the package identifier. MyLib.pm can be written like
> this:
> package MyLib;
>
> sub lib_func
> {
>   ...
> }
> ...
>
> After making that change, your scripts should invoke MyLib::lib_func()
> rather than  lib_func().
>
> Alguém sabe como resolver este problema ?
>
> Agradeço a atenção dispensada ,
>
> kleber
> _______________________________________________
> Cascavel-pm mailing list
> Cascavel-pm em pm.org
> http://mail.pm.org/mailman/listinfo/cascavel-pm
>
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/cascavel-pm/attachments/20141213/e5b730e9/attachment-0001.html>


Mais detalhes sobre a lista de discussão Cascavel-pm