You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2001/09/07 10:56:30 UTC
RFC: Apache::Registry family re-design
This is a proposal paper for Apache::Registry for mod_perl 2.0.
The whole family of Apache::Registry-like modules can be transformed
from hardcoded packages with specified functionality into a what I
call Apache::Registry::Cooker packages.
Since various users will want various behavior from various registry
modules, it'll be too cumbersome to create and maintain all possible
variations. Of course this could be implemented as a sub-classable
system, where users wishing their own behavior, need to subclass
whichever existing module whose behavior is the closest to the desired
one. I believe that compiling the registry package on the fly will
make things more flexible.
So I suggest the following spec:
Apache::Registry::Cooker - cook the desired registry handler.
e.g. put in startup.pl:
use Apache::Registry::Cooker;
Apache::Registry::Cooker::cook
({
package => 'MyCoolRegistry',
key_alg => 'filename', # (or inode, or uri, or vh+uri, ...)
stat_src => 1, (0 not to stat on each request)
flush => 0, # flush namespace on each request
... # more features to come
});
In httpd.conf you just write:
PerlHandler MyCoolRegistry;
The cooker will do something like the following:
use Apache::Registry::Base ();
sub cook{
my $cook = shift;
my $package = $cook->{package} or die "package is not specified";
my $debug = $cook->{debug} || 0;
my $stat_src = $cook->{stat_src} || 0;
my $key_alg_sub = $Apache::Registry::Base::algs{$cook->{key_alg}};
my $package_code = << "EOP";
package $package;
use constant DEBUG => $debug;
use constant STAT_SRC => $stat_src;
*handler = *Apache::Registry::Base::handler{CODE};
*sub_wrap = *Apache::Registry::Base::sub_wrap_def{CODE};
*sub_package_name = $key_alg_sub\{CODE};
1;
EOP
eval $package_code;
}
As you can see it generates a package with the name provided by user,
and autovivify the package with requested features, by aliasing the
methods in this new package to the base of existing components, which
can be implemented in Perl or XS.
Now since we want to keep the old names with their predefined behavior
around, it's very easy. e.g. take Apache::PerlRun
package Apache::PerlRun;
Apache::Registry::Cooker::cook
(
package => 'Apache::PerlRun',
key_alg => 'uri', # (or inode, or uri, or vh+uri, ...)
stat_src => 1, (0 not to stat on each request)
flush => 1, # flush namespace on each request
);
1;
Now to use it you just do:
PerlModule Apache::PerlRun
<Location /dirty>
..
PerlHandler Apache::PerlRun
</Location>
Now Apache::Registry::Cooker may use many packages which specialize in
something specific, for example Apache::Registry::Flush will
concentrate on namespace flushing. This will allow us nice separation
of various functionalities in various packages.
Now about debug mode, each package may define debug code, which via
cook() interface may be enabled at compile time, so you can see
various status dumps in error_log. Since we don't want debug code to
slow down run time, this all has to be done via constants, which means
that if you enable debugging for one function it'll be enabled for all
cooked packages that use this function (in this function).
The code will try to use as many constants as possible to make the
code as optimizes as possible. Obviously for the best performance the
registry packages are to be cooked at the server startup.
Once the basic Perl components are written we can start working on XS
replacements for these components.
But the first step is to write (port) a modular Apache::Registry as we
know it today with 1.x, make it work with 2.x. This is something that
I'm going to start with.
Problems that existed in Registry modules in mod_perl 1.x that need to
be solved:
* __DATA__ and __END__ tokens: should read the file till these tokens
are met and compile only the code that has been read so far.
* the issue with closures: Should we try to solve it or keep on
explaining the problem? You input is welcome. If you think we should
solve it please suggest how.
* global variables persistance: I suggest to have the cooker option to
flash only globals at the end of each request. Of course this
extends only to the autogenerated package, and not modules used out
of this package.
* compiled regex with /o problem: leave it as is or handle it?
* probably need to try to handle the problem with libs collisions as
explained here:
http://perl.apache.org/guide/porting.html#Name_collisions_with_Modules_and
Not sure yet how to do that.
* It's a known kludge with mod_perl scripts when you use a script
coming from mod_cgi which uses -M for file comparisons, but is not
aware of the fact that $^T is not getting reset on each request. So
may be the cooker should have an option to reset $^T if requested.
* any other issues to solve?
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Fri, 7 Sep 2001, raptor wrote:
> | * the issue with closures: Should we try to solve it or keep on
> | explaining the problem? You input is welcome. If you think we should
> | solve it please suggest how.
> ]- solve it .... i don't know how too :")
> | * probably need to try to handle the problem with libs collisions as
> | explained here:
> | http://perl.apache.org/guide/porting.html#Name_collisions_with_Modules_and
> | Not sure yet how to do that.
> ]- partial solution ... what if when the module is compiled the sub-name to
> include the VirtualHost-ServerName, this way modules on diff host will not
> collide..
That won't really work, since it's possible that some file required from
.pl will require some other file. Now think about eval that build require
calls from strings.
However it won't be a problem with vh's at all, assuming that you assign a
different interpreter pools for different vh's. The problem is with two
.pl files in the same interpreter calling 'require "foo-lib.pl"' and the
latter doesn't declare package. See the link above that describes the
problem in details.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by raptor <ra...@unacs.bg>.
| * the issue with closures: Should we try to solve it or keep on
| explaining the problem? You input is welcome. If you think we should
| solve it please suggest how.
]- solve it .... i don't know how too :")
| * probably need to try to handle the problem with libs collisions as
| explained here:
| http://perl.apache.org/guide/porting.html#Name_collisions_with_Modules_and
| Not sure yet how to do that.
]- partial solution ... what if when the module is compiled the sub-name to
include the VirtualHost-ServerName, this way modules on diff host will not
collide..
=====
iVAN
raptor@unacs.bg
=====
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Threading issues [Was: RFC: Apache::Registry family re-design]
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 02:10:51PM +0800, Stas Bekman wrote:
> >
> > On a lot of OSs, the cwd is kept as a part of the kernel's
> > per-process structures, so all threads share the same idea of cwd.
> > Anytime you use a userland threads package this is likely.
> >
> > There are other threading prblems, like non-reentrant C RTL calls
> > and old, old APIs like, asctime(), that return pointers to static
> > buffers inside the C RTL. Perl will probably come to use reentrant
> > versions or wrap non-reentrant ones with mutexes and copy off static
> > buffers, or just disable certain calls in threaded mode, but XS code
> > is another kettle of fish. A lot of problems won't show up on
> > single CPU boxes, either, so a lot of people can't test their code
> > in SMP MT environments :-(. Let alone write t/*.t scripts that try
> > to exercise things in a MT fashion.
> >
> > Then there's APIs that are completely non threadsafe, AFAIK, like
> > setjmp/longjmp, which are used in Perl in some farily critical
> > places.
> >
> > All of the above have fixes, not sure how many are practical in
> > perl5.
>
> Argh :( Are there any pointers to read on these issues.
I wish I knew of a good "portable multithreaded programming" primer;
perhaps someone else does. Python's been up this curve, you might ask
on the language-dev list, and you might look at GNU Pth's docs and at
the various threading FAQs. Curl up with Google by the fireplace for an
evening ;-).
> Shouldn't
> these issues be transparent for the programmers using Perl? Ideally?
Ideally, yes. Perl's headed towards a shared-nothing-by-default
threading paradigm (not just in-process resources, but OS interactions
like signals have to be thought of) and has the ability to work around
(some) non-reentrant or static-buffer-using C RTL APIs and syscall
wrappers, but things like chdir() are a right pain (this will bite on every
platform where userspace threads are used, and on some (eg Netware)
where they aren't).
Perl's approach will also minimize setjmp/longjmp issues, I think, by
not trying to jump between threads. Ask Alan Berlinson for details, he
is rather strident (and needs to be) when commenting on this[1].
Anyway, the bottom line is that things like chdir() are likely to be
non-portable (ok on Linux and maybe Windows, at least, not on FreeBSD,
probably never on NetWare, for instance), most dangerous-today library
calls will have increasing levels of thread safety at noticable cost to
performancs (mutexes, baby, mutexes! [2]), and perl5 will asymtotically
approach thread-safety, perhaps even reach it on "modern" OSs.
This is all IMHO, mostly info gathered a long time ago when convincing
myself that MT coding is for specialized niches where the gain is worth
the pain.
- Barrie
[1]http://archive.develooper.com/perl-ithreads@perl.org/msg00081.html
[2]http://www.timvp.com/kojak.html
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Arthur Bergman <ar...@contiller.se>.
> On Sun, Sep 09, 2001 at 04:49:50PM -0400, Barrie Slaymaker wrote:
> >
> > > However, should threads have different cwds?
> >
> > Well, if you want to use any modules that chdir() in threaded code, I
> > think so. Basically, in a threaded perl, unsafe chdir should be warned
> > about or perl should DWIM and emulate chdir per thread (as it does on
> > windows). The former is the halting problem, I think ;-).
>
> Also, %ENV should probably be thread-localized if it's not, for similar
> reasons.
>
> When Java's designers faced this problem, they just said "thou shalt not
> chdir()". Well, that's one way to do it, or you can be nice and have
> your language say "well, it'll slow things down, but go ahead". The
> only problem I have is that it slows things down whether or not you use
> it (since, for instance, open() needs to at least check the actual dir
> against the current thread's emulated cwd and perhaps do a chdir()
> C RTL call before the open() C RTL call. Or something. But there could
> always be a "don't emulate chdir-per-thread" option, either when
> building perl or at runtime...
>
> - Barrie
>
This could potentially be fixed by an external module which hooks into CORE::GLOBAL::chdir and CORE::GLOBAL::open.
ENV suffers from the same problems I agree. (But ENV cannot be solved by a module).
It could easily be a runtime option, or it could be implmented using iperlsys stuff. However writing a iperlsys layer
is not trivial, and is probably a bigger slowdown than adding the proper code to open. I also would hardly consider chdir+open
to be a hotspot in any larger program.
Arthur
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 04:49:50PM -0400, Barrie Slaymaker wrote:
>
> > However, should threads have different cwds?
>
> Well, if you want to use any modules that chdir() in threaded code, I
> think so. Basically, in a threaded perl, unsafe chdir should be warned
> about or perl should DWIM and emulate chdir per thread (as it does on
> windows). The former is the halting problem, I think ;-).
Also, %ENV should probably be thread-localized if it's not, for similar
reasons.
When Java's designers faced this problem, they just said "thou shalt not
chdir()". Well, that's one way to do it, or you can be nice and have
your language say "well, it'll slow things down, but go ahead". The
only problem I have is that it slows things down whether or not you use
it (since, for instance, open() needs to at least check the actual dir
against the current thread's emulated cwd and perhaps do a chdir()
C RTL call before the open() C RTL call. Or something. But there could
always be a "don't emulate chdir-per-thread" option, either when
building perl or at runtime...
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Mon, Sep 10, 2001 at 10:49:53AM -0400, Barrie Slaymaker wrote:
> On Mon, Sep 10, 2001 at 10:31:48AM +0200, Arthur Bergman wrote:
> >
> > > > How does Apache deal with this?
> > >
> > > By carefully repeating "Don't Do That" as they code the httpd ;-).
> >
> > There are good reasons for this :-)
>
> :-)
>
> > I would suspect linux has a process level chdir, not sure thou.
>
> Just checked, pthread_create() causes all threads to share the cwd and
> umask. By using __clone() directly, they could be set as unshared, I
> think, by passing CLONE_FS.
s/ by passing/ by not passing/. Sorry. And pthread_create does indeed
pass CLONE_FS:
pid = __clone(pthread_start_thread_event, (void **) new_thread,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
__pthread_sig_cancel, new_thread);
Don't think wee want ithreads on linux to not use pthreads, so not
passing CLONE_FS is not really an option...
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Arthur Bergman <ar...@contiller.se>.
> > I would suspect linux has a process level chdir, not sure thou.
>
> Just checked, pthread_create() causes all threads to share the cwd and
> umask. By using __clone() directly, they could be set as unshared, I
> think, by passing CLONE_FS.
So we can easily fix it for linux.
> I guess the bottom line it: Perl seems to be headed towards an emulation
> of multiprocessing (unshared everything by default); how far should it
> go in that direction? The Win32 approach has been to go as far as
> possible to emulate fork(), and I think that that's a good approach,
> since it will lead to least surprises among non-threads programmers.
> The downside is increases complexity and a corresponding performance hit
> (though I think it will usually be minor).
Yes, but we also have the issues of running under threaded perl and running
different perl programs in different threads. %ENV should be shared in the
first case, not in the second. Same with cwd.
> I think that for mod_perl backcompat purposes the more the merrier, so
> that lots of existing modules don't need to be ported to MT-safety. But
> for performance-seekers, that may not be the ideal. Of course "for
> them, there's C" might be an acceptable answer, I dunno.
I don't agree, I think it should an option in perl wheter to share these things or not?
> Things like umask, %ENV, $SIG{__DIE__}, $SIG{__WARN__}, cwd, open files,
> etc. can be copied to get really close to the "ideal", things like euid,
> uid, etc., are more difficult to play pretend with.
>
__DIE__ and __WARN__ should already be per thread. But this is a can of worm, there are many
variables which have to be delt with. $$ for example. Not all platforms give out a different pid for different
threads. Win32 does this by having negative pids.
However, if one wants to solve this properly, one should write a iperlsys layer for unix.
Arthur
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Mon, Sep 10, 2001 at 10:31:48AM +0200, Arthur Bergman wrote:
>
> > > How does Apache deal with this?
> >
> > By carefully repeating "Don't Do That" as they code the httpd ;-).
>
> There are good reasons for this :-)
:-)
> I would suspect linux has a process level chdir, not sure thou.
Just checked, pthread_create() causes all threads to share the cwd and
umask. By using __clone() directly, they could be set as unshared, I
think, by passing CLONE_FS.
I guess the bottom line it: Perl seems to be headed towards an emulation
of multiprocessing (unshared everything by default); how far should it
go in that direction? The Win32 approach has been to go as far as
possible to emulate fork(), and I think that that's a good approach,
since it will lead to least surprises among non-threads programmers.
The downside is increases complexity and a corresponding performance hit
(though I think it will usually be minor).
I think that for mod_perl backcompat purposes the more the merrier, so
that lots of existing modules don't need to be ported to MT-safety. But
for performance-seekers, that may not be the ideal. Of course "for
them, there's C" might be an acceptable answer, I dunno.
Things like umask, %ENV, $SIG{__DIE__}, $SIG{__WARN__}, cwd, open files,
etc. can be copied to get really close to the "ideal", things like euid,
uid, etc., are more difficult to play pretend with.
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Arthur Bergman <ar...@contiller.se>.
> > However, should threads have different cwds?
>
> Well, if you want to use any modules that chdir() in threaded code, I
> think so. Basically, in a threaded perl, unsafe chdir should be warned
> about or perl should DWIM and emulate chdir per thread (as it does on
> windows). The former is the halting problem, I think ;-).
>
> > If so it should probably be solved in perl, but can it be done portable?
>
> Don't see why not. The real oddity here is Windows which has a cwd per
> volume (A:, B:, etc), and that's either ignored in win32.c or emulated
> too, not sure.
> > How does Apache deal with this?
>
> By carefully repeating "Don't Do That" as they code the httpd ;-). The
> cgi-bin chdir() is done after fork()ing, and most (if not all, not sure)
> other chdir()s are pre-thread-startup or when coredumping.
There are good reasons for this :-)
> There was an ap_ chdir() wrapper in existance for a while, but that was
> removed becuase it wasn't threadsafe and not in use.
>
> That all being said, chdir() is probably in use in various Apache
> modules here and there; they'll need a bit of porting for any OS other
> than Linux, I suspect, and perhaps even on Linux (don't know if the cwd
> is part of the process structures that is shared or not, need to spelunk
> & test, unless somebody here knows...).
I would suspect linux has a process level chdir, not sure thou.
> > Sarathy claims that all stjmp/longjmp code is exeucted while not
> > holding any mutexes, so it should be threadsafe. One can note that
> > setjmp and longjmp are not non-mt safe. But they can be used to do
> > unsafe things.
>
> Or they can be used in a safe manner, such as never jumping between
> threads. setjmp() and longjmp() should be safely usable. Is the only
> interaction with mutexes that you need to release any acquired after the
> setjmp() before calling longjmp()?
>
> - Barrie
Yes, as far as I can tell.
Arthur
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 09:30:50PM +0200, Arthur Bergman wrote:
>
> I would suspect that this is solved in the perlhost/perlsys code which is win32 specific.
> There is nothiing in ithreads that does this.
Rats.
> Relevant code is iperlsys.h PerlDir_chdir.
Thanks.
> However, should threads have different cwds?
Well, if you want to use any modules that chdir() in threaded code, I
think so. Basically, in a threaded perl, unsafe chdir should be warned
about or perl should DWIM and emulate chdir per thread (as it does on
windows). The former is the halting problem, I think ;-).
> If so it should probably be solved in perl, but can it be done portable?
Don't see why not. The real oddity here is Windows which has a cwd per
volume (A:, B:, etc), and that's either ignored in win32.c or emulated
too, not sure.
> How does Apache deal with this?
By carefully repeating "Don't Do That" as they code the httpd ;-). The
cgi-bin chdir() is done after fork()ing, and most (if not all, not sure)
other chdir()s are pre-thread-startup or when coredumping.
There was an ap_ chdir() wrapper in existance for a while, but that was
removed becuase it wasn't threadsafe and not in use.
That all being said, chdir() is probably in use in various Apache
modules here and there; they'll need a bit of porting for any OS other
than Linux, I suspect, and perhaps even on Linux (don't know if the cwd
is part of the process structures that is shared or not, need to spelunk
& test, unless somebody here knows...).
> Sarathy claims that all stjmp/longjmp code is exeucted while not
> holding any mutexes, so it should be threadsafe. One can note that
> setjmp and longjmp are not non-mt safe. But they can be used to do
> unsafe things.
Or they can be used in a safe manner, such as never jumping between
threads. setjmp() and longjmp() should be safely usable. Is the only
interaction with mutexes that you need to release any acquired after the
setjmp() before calling longjmp()?
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
RE: RFC: Apache::Registry family re-design
Posted by Ask Bjoern Hansen <as...@valueclick.com>.
On Sun, 9 Sep 2001, Arthur Bergman wrote:
> > Thank you for forwarding that, I've not seen it on-list before. Good to
> > know.
>
> Sarathy claims that all stjmp/longjmp code is exeucted while not holding any mutexes,
> so it should be threadsafe. One can note that setjmp and longjmp are not non-mt safe.
> But they can be used to do unsafe things.
I know Arthur have seen this, but for the benefits of others: The
"Parrot multithreading" thread on
news://nntp.perl.org/perl.perl6.internals is talking about this.
<snip>
Date: Fri, 28 Sep 2001 12:01:44 +0100
From: Alan Burlison <Al...@sun.com>
Subject: Re: SV: Parrot multithreading?
References: <Pi...@copland.udel.edu> <3B...@sun.com> <000b01
c1480a$1ee520d0$21000a0a@vogw2kdev>
Arthur Bergman wrote:
> longjmp in a controlled fashion isn't thread-safe? Or longjmping while holding mutexs and out from asynch
ronous handlers is not
> thread-safe?
>
> Arthur
$man longjmp
...
ATTRIBUTES
See attributes(5) for descriptions of the following attri-
butes:
____________________________________________________________
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
|_____________________________|_____________________________|
| MT-Level | Unsafe |
|_____________________________|_____________________________|
...
It *may* be possible to use longjmp in threaded programs in a restricted
fashion on some platforms. However if you use it on Solaris, for example,
where we don't commit to it being thread-safe and it breaks - tough. This
includes breakage introduced by either new patches or new OS releases, as
we haven't committed to it being thread-safe in the first place.
mutexes and CVs are one issue, but you can't assume that the code that
saves/restores the stack context is thread-safe either. And as for what
might happen if you setjmp in one thread and longjmp from a different one
- Eeek! Also, generally speaking you shouldn't be using signal handlers
in threaded code either.
I'm assuming that the overriding aim is portability, in which case
threads, signal handlers and longjmp definitely don't mix.
--
Alan Burlison
</snip>
- ask
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
RE: RFC: Apache::Registry family re-design
Posted by Arthur Bergman <ar...@contiller.se>.
> On Sun, Sep 09, 2001 at 10:23:49AM -0700, Doug MacEachern wrote:
> > On Sat, 8 Sep 2001, Barrie Slaymaker wrote:
> >
> > > On a lot of OSs, the cwd is kept as a part of the kernel's per-process
> > > structures, so all threads share the same idea of cwd. Anytime you use
> > > a userland threads package this is likely.
> >
> > we should be able to set things up so chdir() is a noop, and just adjust
> > the enviornent (@INC, $ENV{PATH}, open, etc) to use basename $0 instead of
> > '.'
>
> Looks like ithreads, or at least the win32 subsystem of Perl already
> does this, according to perlfork. If it's not ithreads-general yet
> (haven't had time to spelunk in to find this out), it will need to be on
> most platforms, I think.
I would suspect that this is solved in the perlhost/perlsys code which is win32 specific.
There is nothiing in ithreads that does this. Relevant code is iperlsys.h PerlDir_chdir.
On unix this is
#define PerlDir_chdir(name) chdir((name))
VMS
# define PerlDir_chdir(n) Chdir(((n) && *(n)) ? (n) : "SYS$LOGIN"))
on windows however (or any other with non implicit sys) it is
(*PL_Dir->pChdir)(PL_Dir, (name))
This probably is where windows does it safe thing. However, should threads have
different cwds? If so it should probably be solved in perl, but can it be done portable?
How does Apache deal with this?
> > > Then there's APIs that are completely non threadsafe, AFAIK, like
> > > setjmp/longjmp, which are used in Perl in some farily critical places.
> >
> > not an issue according to sarathy..
>
> Thank you for forwarding that, I've not seen it on-list before. Good to
> know.
>
Sarathy claims that all stjmp/longjmp code is exeucted while not holding any mutexes,
so it should be threadsafe. One can note that setjmp and longjmp are not non-mt safe.
But they can be used to do unsafe things.
Arthur
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 10:23:49AM -0700, Doug MacEachern wrote:
> On Sat, 8 Sep 2001, Barrie Slaymaker wrote:
>
> > On a lot of OSs, the cwd is kept as a part of the kernel's per-process
> > structures, so all threads share the same idea of cwd. Anytime you use
> > a userland threads package this is likely.
>
> we should be able to set things up so chdir() is a noop, and just adjust
> the enviornent (@INC, $ENV{PATH}, open, etc) to use basename $0 instead of
> '.'
Looks like ithreads, or at least the win32 subsystem of Perl already
does this, according to perlfork. If it's not ithreads-general yet
(haven't had time to spelunk in to find this out), it will need to be on
most platforms, I think.
> > Then there's APIs that are completely non threadsafe, AFAIK, like
> > setjmp/longjmp, which are used in Perl in some farily critical places.
>
> not an issue according to sarathy..
Thank you for forwarding that, I've not seen it on-list before. Good to
know.
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 10:50:37PM +0800, Stas Bekman wrote:
> On Sun, 9 Sep 2001, Barrie Slaymaker wrote:
>
> > On Sun, Sep 09, 2001 at 02:10:51PM +0800, Stas Bekman wrote:
> > >
> > > Argh :( Are there any pointers to read on these issues.
> >
> > Gah, forgot to mention perthrtut!
>
> which doesn't exists in perl <= 5.6.1, and in 5.7.2 it says:
s/<=/</, 5.6.1 is where I found it. If you read through that version
with the mantra "the perlish part of this is all changing", then it
gives a nice overview of the various issues with MT.
> This document is unfortunately rather sparse as of
> 2001-Sep-17.
:-).
> :) Not talking that it redirects the readers to perlothrtut.pod, which at
> least has some meat.
Odd, I see it in pod/perlthrtut.pod in 5.7.2 I rsynced last week:
[barries@//sizzle] perl-current$ ls -l pod/*thr*
-r--r--r-- 1 barries 40802 Aug 28 2000 pod/perlthrtut.pod
some rsync oddity, I guess...
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Sun, 9 Sep 2001, Barrie Slaymaker wrote:
> On Sun, Sep 09, 2001 at 02:10:51PM +0800, Stas Bekman wrote:
> >
> > Argh :( Are there any pointers to read on these issues.
>
> Gah, forgot to mention perthrtut!
which doesn't exists in perl <= 5.6.1, and in 5.7.2 it says:
This document is unfortunately rather sparse as of
2001-Sep-17.
So the author lives in the future, and the future doesn't seem to be good
:) Not talking that it redirects the readers to perlothrtut.pod, which at
least has some meat.
Now I have something to read :) thanks Barrie.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 02:10:51PM +0800, Stas Bekman wrote:
>
> Argh :( Are there any pointers to read on these issues.
Gah, forgot to mention perthrtut!
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Sat, 8 Sep 2001, Barrie Slaymaker wrote:
> On Sun, Sep 09, 2001 at 01:19:01AM +0800, Stas Bekman wrote:
> >
> > Who said that we have to use prototypes? Or if we don't the sub call won't
> > be optimized away?
>
> Yup. Gotta have that () prototype, it's a bit of a (pragmatic) kludge.
> If it were done today it would probably be via a ":constant" attributes
> so's you could have constant subvs w/ mult. attrs. Or something.
I guess we can use the ":constant" attribute, I think so far we require
that perl >= v5.6.0. I'd even say v5.6.1, since 5.6.0 is very buggy.
> Anway, see perlsub.
Yup, thanks for the pointer. I was using constant pragma for constants, so
I wasn't aware of the () issue.
> > $ perl -lwe "sub NOP{};NOP('a')"
>
> FWIW (had to give NOP a return value):
>
> $ perl -MO=Terse -we "sub NOP{1};NOP()"
> Use of uninitialized value in string eq at /usr/local/lib/perl5/5.6.0/i686-linux/B/Terse.pm line 31.
> LISTOP (0x8173648) leave
> OP (0x8173670) enter
> COP (0x8173610) nextstate
> UNOP (0x81735f0) entersub [1]
> UNOP (0x81735a8) null [141]
> OP (0x81735d0) pushmark
> UNOP (0x8173588) null [17]
> SVOP (0x816e850) gv GV (0x818c544) *NOP
> -e syntax OK
> $ perl -MO=Terse -we "sub NOP(){1};NOP()"
> Use of uninitialized value in string eq at /usr/local/lib/perl5/5.6.0/i686-linux/B/Terse.pm line 31.
> LISTOP (0x81735f0) leave
> OP (0x80f5a40) enter
> COP (0x81735b8) nextstate
> OP (0x816e850) null [5]
> -e syntax OK
Terse is cool :)
> > Yes, you understood it correctly. In fact I didn't yet think about the
> > details. I suppose we can always use CGI.pm approach and build the code
> > via Autoload. then we can really optimize things ourselves, by writing
> > only the code that we need. This will make the code writing harder, but
> > it's possible. The real problem will be with XS versions of the subs,
> > where it simply won't work, unless we use lots of #IFDEFS, I guess that's
> > the only way to go there.
>
> Hmmm, Inline comes to mind, but that requires a C compiler at run-time.
You mean writing the C code with Perl on the fly and then compile with
Inline. Neat. At least this can be done at install time when you craft a
set of modules with predefined functionality.
> > Nuh, we should stay away from using globals. Hmm, is it possible to write
> > the NOP in XS? it still has to be CODE reference. Any XS gurus?
>
> No, the sub call to the XS could would be optimized away; that's the
> whole point of the constant sub optimization.
right.
We still don't have to use globals. We can write a known closure sub that
will return the arguments, like filename to stat. Or since we have the
internal CACHE of code anyway, we could store the attributes in there. So
we end up with a single global storage, which can be shared between
threads via solar var mechanism.
> > But what problem are we trying to solve here?
>
> closures. Basically, if you can't be bothered to (or afford to)
> refactor your code, then having the parse "sense" lexical globals and
> named sub decls in some way would be helpful. Given the difficulties of
> parsing Perl, I figured maybe defining a tag that let you tell the
> parser to partition your code for you might be cool. Or maybe not; been
> a long time since I had to convert a crufty ol' CGI.
I really don't think that in reality it will work in most cases.
It seems that the goto() trick suggested by raptor, can solve the
closure problem. Need to look more into it.
> > That shouldn't be a problem. If we design this system as flexible as
> > possible, we can try to provide a new handler which does what you suggest
> > and then if it works well and doesn't add a big overhead, than we can
> > replace the previous one with the latter one. Adding
> > ##__REGISTRY_HANDLER__ shouldn't add any overhead at all, but that's only
> > in case where the script is preloaded.
>
> preloaded? Or loaded once? I'm assuming the latter; meaning the script
> isn't loaded and compiled every request, not that it's preloaded at
> (re)start time.
yes.
> > please give me a short example of the template you are talking about.
>
> Here's a slightly cleaned up example from my first message, an example
> of a custom one I might want to write so all my scripts get run in a
> custom environment:
>
> package <%= $h->{package_name} %> ;
>
> use strict ; ## or not...
> use My::Standard::Lib ;
> use Apache::Util ;
> use Apache::File ;
> use Apache::Constant ;
> use My::Application::Lib ;
> use GD ;
>
> *dbh = *My::Globals::dbh ;
>
> ## etc., etc.
>
> use base qw( My::AppBase ) ;
>
> ## Some little utility routines...
> sub empty { ! defined $_[0] || ! length $_[0] }
> ## etc.
>
> sub handler {
> my ( $r ) = Apache::Request->new( shift ) ;
> #line 1 <%= $h->{script_file_name} %>
> {<%= $h->{script_body} %>} ;
> return OK ;
> }
>
> 1 ;
>
> Apache::Registry could have a (use-constant-optimizable) option to
> read a file like this and convert it in to code to be cooked like:
>
> *handler = *some_handler_from_your_example ;
> *mtime = *mtime_getter ;
>
> sub gen_code {
> my $h = shift ;
> join(
> 'package ', $h->{package_name}, ' ;
>
> use strict ; ## or not...
> use My::Standard::Lib ;
> use Apache::Util ;
> use Apache::File ;
> use Apache::Constant ;
> use My::Application::Lib ;
> use GD ;
>
> *dbh = *My::Globals::dbh ;
>
> ## etc., etc.
>
> use base qw( My::AppBase ) ;
>
> ## Some little utility routines...
> sub empty { ! defined $_[0] || ! length $_[0] }
> ## etc.
>
> sub handler {
> my ( $r ) = Apache::Request->new( shift ) ;
> #line 1 ', $h->script_file_name, '
> {', $h->{script_body} '} ;
> return OK ;
> }
>
> 1 ;' ) ;
> }
>
> It's just a handy way of letting people define the environment that
> their scripts get called in.
Looks neat, but then when you write your scripts you should be aware that
some things happen behind the scenes. I guess one just have to put their
head into a different state :)
But I don't see any problem with this. This should work out of box.
> > > 'nuther issue: what's the plan to make it threaded-MPM compatible given
> > > that it does a chdir() and calls
> >
> > Hmm, I really have to start digging into the threading issues, I've
> > ignored them so far. Is chdir() not thread-safe? If you chdir in one
> > thread, does it affect other threads? Also what other calls you are
> > talking about?
>
> On a lot of OSs, the cwd is kept as a part of the kernel's per-process
> structures, so all threads share the same idea of cwd. Anytime you
> use a userland threads package this is likely.
>
> There are other threading prblems, like non-reentrant C RTL calls and
> old, old APIs like, asctime(), that return pointers to static buffers
> inside the C RTL. Perl will probably come to use reentrant versions
> or wrap non-reentrant ones with mutexes and copy off static buffers,
> or just disable certain calls in threaded mode, but XS code is another
> kettle of fish. A lot of problems won't show up on single CPU boxes,
> either, so a lot of people can't test their code in SMP MT
> environments :-(. Let alone write t/*.t scripts that try to exercise
> things in a MT fashion.
>
> Then there's APIs that are completely non threadsafe, AFAIK, like
> setjmp/longjmp, which are used in Perl in some farily critical places.
>
> All of the above have fixes, not sure how many are practical in perl5.
Argh :( Are there any pointers to read on these issues. I understand the
problem(s) now, where do I learn about the solutions? Shouldn't these
issues be transparent for the programmers using Perl? Ideally?
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Doug MacEachern <do...@covalent.net>.
On Sat, 8 Sep 2001, Barrie Slaymaker wrote:
> On a lot of OSs, the cwd is kept as a part of the kernel's per-process
> structures, so all threads share the same idea of cwd. Anytime you use
> a userland threads package this is likely.
we should be able to set things up so chdir() is a noop, and just adjust
the enviornent (@INC, $ENV{PATH}, open, etc) to use basename $0 instead of
'.'
> Then there's APIs that are completely non threadsafe, AFAIK, like
> setjmp/longjmp, which are used in Perl in some farily critical places.
not an issue according to sarathy..
To: Doug MacEachern <do...@covalent.net>
Subject: Re: 5.6.1+ithreads
Date: Sun, 26 Aug 2001 23:01:48 -0700
From: Gurusamy Sarathy <gs...@ActiveState.com>
On Sun, 26 Aug 2001 22:22:46 PDT, Doug MacEachern wrote:
>On Sun, 26 Aug 2001, Gurusamy Sarathy wrote:
>
>> Aside from forcing the use of setjmp() instead of sigsetjmp() et al, I'm
>> not aware of any issues with setjmp(). Do you have anything more specific
>> on that?
>
>just what alan burlison has brought up on p5p:
>http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-05/msg00805.html
AFAIK, that issue only applies to sig{set,long}jmp() and is specific
to Solaris. There's no global state involved in {set,long}jmp() so
they're safe to use within the same thread. The setjmp/longjmp
reference in this page would appear to confirm this for Solaris:
http://www.sun.com/smcc/solaris-migration/docs/courses/threadsHTML/adv.html
We do ActivePerl builds here with -Ud_sigsetjmp.
Sarathy
gsar@ActiveState.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sun, Sep 09, 2001 at 01:19:01AM +0800, Stas Bekman wrote:
>
> Who said that we have to use prototypes? Or if we don't the sub call won't
> be optimized away?
Yup. Gotta have that () prototype, it's a bit of a (pragmatic) kludge.
If it were done today it would probably be via a ":constant" attributes
so's you could have constant subvs w/ mult. attrs. Or something.
Anway, see perlsub.
> $ perl -lwe "sub NOP{};NOP('a')"
FWIW (had to give NOP a return value):
$ perl -MO=Terse -we "sub NOP{1};NOP()"
Use of uninitialized value in string eq at /usr/local/lib/perl5/5.6.0/i686-linux/B/Terse.pm line 31.
LISTOP (0x8173648) leave
OP (0x8173670) enter
COP (0x8173610) nextstate
UNOP (0x81735f0) entersub [1]
UNOP (0x81735a8) null [141]
OP (0x81735d0) pushmark
UNOP (0x8173588) null [17]
SVOP (0x816e850) gv GV (0x818c544) *NOP
-e syntax OK
$ perl -MO=Terse -we "sub NOP(){1};NOP()"
Use of uninitialized value in string eq at /usr/local/lib/perl5/5.6.0/i686-linux/B/Terse.pm line 31.
LISTOP (0x81735f0) leave
OP (0x80f5a40) enter
COP (0x81735b8) nextstate
OP (0x816e850) null [5]
-e syntax OK
> Yes, you understood it correctly. In fact I didn't yet think about the
> details. I suppose we can always use CGI.pm approach and build the code
> via Autoload. then we can really optimize things ourselves, by writing
> only the code that we need. This will make the code writing harder, but
> it's possible. The real problem will be with XS versions of the subs,
> where it simply won't work, unless we use lots of #IFDEFS, I guess that's
> the only way to go there.
Hmmm, Inline comes to mind, but that requires a C compiler at run-time.
> Nuh, we should stay away from using globals. Hmm, is it possible to write
> the NOP in XS? it still has to be CODE reference. Any XS gurus?
No, the sub call to the XS could would be optimized away; that's the
whole point of the constant sub optimization.
> I guess just like Apache::DBI, we can make some Apache::Reload::Registry
> and make it and Apache::Reaload to be aware of each other, and interact in
> the way you suggest.
Just trying to get that code sharing & reuse thang going...
> > > Hmm, that's an interesting idea. But won't it confuse users even more?
> > > this will require them to move all the none-handler code up, or we need
> > > something like: ##__REGISTRY_HANDLER_END__ as well.
> >
> > My experience is that most CGI scripts require munging to run nicely
> > under Apache::Registry anyway, but YMMV. Just looking to make the
> > munging easier.
>
> I doubt that your code example in your original post is a typical one.
Yup, it was too clean to start with.
> Usually people scatter their handler code across many subs and I'm not
> sure how ##__REGISTRY_HANDLER_END__ can really help.
All those subs would go before ##__REGISTRY_HANDLER__ or after your
##__REGISTRY_HANDLER_END__
> But what problem are we trying to solve here?
closures. Basically, if you can't be bothered to (or afford to)
refactor your code, then having the parse "sense" lexical globals and
named sub decls in some way would be helpful. Given the difficulties of
parsing Perl, I figured maybe defining a tag that let you tell the
parser to partition your code for you might be cool. Or maybe not; been
a long time since I had to convert a crufty ol' CGI.
> That shouldn't be a problem. If we design this system as flexible as
> possible, we can try to provide a new handler which does what you suggest
> and then if it works well and doesn't add a big overhead, than we can
> replace the previous one with the latter one. Adding
> ##__REGISTRY_HANDLER__ shouldn't add any overhead at all, but that's only
> in case where the script is preloaded.
preloaded? Or loaded once? I'm assuming the latter; meaning the script
isn't loaded and compiled every request, not that it's preloaded at
(re)start time.
> register some hook to do something. The only difference is that we allow
> only one hook per single phase. Or do you think you may want to run a few
> different hooks and make it really like Apache hooks, where each hook
> decides whether it wants to handle the current phase or not? I think that
> would slow things down, since we will need to provide the whole mechanism
> with calls.
No, one handler is fine with a few overloadable (either through OO
inheritence or your cookery) subroutines.
> I guess I'm not very clear on what you are trying to accomplish.
An easy way for people to define the working environment for their
scripts.
> please give me a short example of the template you are talking about.
Here's a slightly cleaned up example from my first message, an example
of a custom one I might want to write so all my scripts get run in a
custom environment:
package <%= $h->{package_name} %> ;
use strict ; ## or not...
use My::Standard::Lib ;
use Apache::Util ;
use Apache::File ;
use Apache::Constant ;
use My::Application::Lib ;
use GD ;
*dbh = *My::Globals::dbh ;
## etc., etc.
use base qw( My::AppBase ) ;
## Some little utility routines...
sub empty { ! defined $_[0] || ! length $_[0] }
## etc.
sub handler {
my ( $r ) = Apache::Request->new( shift ) ;
#line 1 <%= $h->{script_file_name} %>
{<%= $h->{script_body} %>} ;
return OK ;
}
1 ;
Apache::Registry could have a (use-constant-optimizable) option to read a file
like this and convert it in to code to be cooked like:
*handler = *some_handler_from_your_example ;
*mtime = *mtime_getter ;
sub gen_code {
my $h = shift ;
join(
'package ', $h->{package_name}, ' ;
use strict ; ## or not...
use My::Standard::Lib ;
use Apache::Util ;
use Apache::File ;
use Apache::Constant ;
use My::Application::Lib ;
use GD ;
*dbh = *My::Globals::dbh ;
## etc., etc.
use base qw( My::AppBase ) ;
## Some little utility routines...
sub empty { ! defined $_[0] || ! length $_[0] }
## etc.
sub handler {
my ( $r ) = Apache::Request->new( shift ) ;
#line 1 ', $h->script_file_name, '
{', $h->{script_body} '} ;
return OK ;
}
1 ;' ) ;
}
It's just a handy way of letting people define the environment that
their scripts get called in.
> > 'nuther issue: what's the plan to make it threaded-MPM compatible given
> > that it does a chdir() and calls
>
> Hmm, I really have to start digging into the threading issues, I've
> ignored them so far. Is chdir() not thread-safe? If you chdir in one
> thread, does it affect other threads? Also what other calls you are
> talking about?
On a lot of OSs, the cwd is kept as a part of the kernel's per-process
structures, so all threads share the same idea of cwd. Anytime you use
a userland threads package this is likely.
There are other threading prblems, like non-reentrant C RTL calls and
old, old APIs like, asctime(), that return pointers to static buffers
inside the C RTL. Perl will probably come to use reentrant versions or
wrap non-reentrant ones with mutexes and copy off static buffers, or
just disable certain calls in threaded mode, but XS code is another
kettle of fish. A lot of problems won't show up on single CPU boxes,
either, so a lot of people can't test their code in SMP MT environments
:-(. Let alone write t/*.t scripts that try to exercise things in a MT
fashion.
Then there's APIs that are completely non threadsafe, AFAIK, like
setjmp/longjmp, which are used in Perl in some farily critical places.
All of the above have fixes, not sure how many are practical in perl5.
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Mon, 17 Sep 2001, Ken Williams wrote:
>
> Stas Bekman <st...@stason.org> wrote:
> > The point is to write a library of standalone functions implemented in
> > Perl and C, and let the final products be Lego-like, just pick what you
> > want and if you want to have 10 different Registry modules, doing
> > similar but yet different things, you can do it with a little effort.
>
> Why not just use PerlSetVar directives for this, though? They seem more
> like features of a single handler than like different handlers. If you
> implement them as PerlSetVar options, then the functionality could be
> available to Registry, PerlRun, and all the other handlers in that
> inheritance tree.
Ken, please read the thread. I believe there will be possible to write
different configuration interfaces, so you can pick your preferable one.
Since Apache::Registry and Apache::PerlRun and BB and NG should stay as
before, we need to have programmatical configuration interface as well.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Ken Williams <ke...@forum.swarthmore.edu>.
Stas Bekman <st...@stason.org> wrote:
> The point is to write a library of standalone functions implemented in
> Perl and C, and let the final products be Lego-like, just pick what you
> want and if you want to have 10 different Registry modules, doing
> similar but yet different things, you can do it with a little effort.
Why not just use PerlSetVar directives for this, though? They seem more
like features of a single handler than like different handlers. If you
implement them as PerlSetVar options, then the functionality could be
available to Registry, PerlRun, and all the other handlers in that
inheritance tree.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Sat, 8 Sep 2001, Barrie Slaymaker wrote:
> On Sat, Sep 08, 2001 at 05:41:12PM +0800, Stas Bekman wrote:
> > On Fri, 7 Sep 2001, Barrie Slaymaker wrote:
> >
> > > On Fri, Sep 07, 2001 at 04:56:30PM +0800, Stas Bekman wrote:
> >
> > It won't be too confusing for most of the people since they will just use
> > Apache::Registry or Apache::PerlRun as before, without even knowing that
> > these are not real modules anymore.
>
> Figured such "passive use" would be backward compatible, the custom
> directives should allow for slight tweaking without having to think of
> cooking or subclassing.
>
> I'm still pondering whether the complexity of cooking is worth the
> minor speed improvement; it's a really elegant approach to
> hyper-optimizing, but the few extra conditionals that cooking
> optimizes away will be extremely minor compared with both (A) the
> speedup of using Apache::Registry in the first place and (B) the speed
> of the script. I think the performance benefits will be swamped by
> the other parts of the system. But if it's really simple to
> implement, I see no problem with it. It is a neat technical approach.
Well, we will do it because we can and it doesn't take much of an effort,
just like you said. And the best thing is that it doesn't cast anything in
stone, if at some point we find some better way or somebody just want to
go the academic way and make it OO and do all the inheritance staff, you
still can.
The point is to write a library of standalone functions implemented in
Perl and C, and let the final products be Lego-like, just pick what you
want and if you want to have 10 different Registry modules, doing similar
but yet different things, you can do it with a little effort.
As for performance, I do want to have the Registry stuff as fast as
possible. Even if the performance gains are very small. Again we can
afford doing that, without spending too much time, because we can. So I
see no reason why we shouldn't do it.
Rewriting some of the Registry components in XS/C would be definitely a
good thing to do, but this can always be done later. Especially since Doug
has already written Apache::PerlRunXS, which I even didn't know about. Of
course it'll have to be adjusted for apache 2.0 and possible threads
issues, but it's a good start.
> > > For instance, setting root of the namespace the script/handler is
> > > compiled in to and the algorithm used to generate the relative part of
> > > the namespace should be able to be set by a parameter. That might be
> > > configured using perlish interpolation:
> > >
> > > PerlRegistryNameSpace MyRegistryRoot::${filename}
> > >
> > > where $filename/$inode/$uri/$vh is escaped to be a nice package name.
> > > This leads to the natural
> > >
> > > PerlRegistryNameSpace MyRegistryRoot::${vh}::${filename}
> > >
> > > and the slightly unnatural:
> > >
> > > PerlRegistryNameSpace MyRegistryRoot::&{My::key_generating_sub}
> > >
> > > or:
> > >
> > > PerlRegistryNameSpace &{My::key_generating_sub}
> > >
> > > to allow some subroutine to be called to generate the name.
> >
> > I think that all directives in httpd.conf or cook() should accept a
> > reference to a sub, so you can write any sub anywhere and use it. One of
> > the most important benefits of it is using NOPs.
> >
> > package Foo;
> > use constant NOP => sub {};
> >
> > now is it really getting optimized away at compile time?
>
> Depends on how you use it. Do you intend to do something like having
> PerlRegistryDoStat Foo::NOP cause a cooked package to do something like
>
> *do_stat = *Foo::NOP ;
>
> ...some lines later...
>
> $mtime = (do_stat($filename))[9];
yup.
> ? I think that'll barf due to passing in a parameter to a sub with a ()
> prototype:
>
> $ perl -we "sub NOP(){};NOP('a')"
> Too many arguments for main::NOP at -e line 1, at end of line
> Execution of -e aborted due to compilation errors.
Who said that we have to use prototypes? Or if we don't the sub call won't
be optimized away?
$ perl -lwe "sub NOP{};NOP('a')"
is there some doc explaining how things getting optimized away, other than
the source code?
> Perhaps better for httpd.conf readability to use a special value of
> "Off" to force a NOP, "On" for default operation, and "SubName" to cook
> code like:
>
> use constant get_mtime => "" ;
>
> ...some lines later....
>
> my $mtime ;
> $mtime = lc get_mtime eq "On" ? (stat $fn)[9] : get_mtime->()
> if get_mtime && lc get_mtime ne "off" ;
>
> That rather complex expression should optimize away nicely for /off/i ;
>
> Or did I misunderstand your intent?
Yes, you understood it correctly. In fact I didn't yet think about the
details. I suppose we can always use CGI.pm approach and build the code
via Autoload. then we can really optimize things ourselves, by writing
only the code that we need. This will make the code writing harder, but
it's possible. The real problem will be with XS versions of the subs,
where it simply won't work, unless we use lots of #IFDEFS, I guess that's
the only way to go there.
> > Or is there some better way to make NOP CODE reference?
>
> I don't think there's a really good way to do a NOP code ref. Of course
> you could pass the filename in a global to avoid the prototype vs. arg.
> passing issue, but that's a tad messy.
Nuh, we should stay away from using globals. Hmm, is it possible to write
the NOP in XS? it still has to be CODE reference. Any XS gurus?
> > > It'd be nice if the new Apache::Registry could use or just cooperate
> > > with Apache::Reload for autostat/autoreload.
> >
> > That won't really work. Because the files on the disk aren't the same as
> > registry packages, unless Apache::Reload will try to use a known interface
> > to package_reload in the registry space, but I see no why how
> > Apache::Reload will figure out what registry package in %INC belongs to
> > what Apache::RegistryFoo module.
>
> Not sure it will out of the gate, but either tweaking Apache::Reload to
> know about files so
>
> use Apache::Reload "/path/to/perlrun/script" ;
>
> would DWIM (analogous to require "/path/to/perllib" vs. require Module).
> Or a subclass of Apache::Reload, altering package_to_module()'s
> behavior. Making Apache::Reload more flexible would be a good thing.
I guess just like Apache::DBI, we can make some Apache::Reload::Registry
and make it and Apache::Reaload to be aware of each other, and interact in
the way you suggest.
> > Hmm, that's an interesting idea. But won't it confuse users even more?
> > this will require them to move all the none-handler code up, or we need
> > something like: ##__REGISTRY_HANDLER_END__ as well.
>
> My experience is that most CGI scripts require munging to run nicely
> under Apache::Registry anyway, but YMMV. Just looking to make the
> munging easier.
I doubt that your code example in your original post is a typical one.
Usually people scatter their handler code across many subs and I'm not
sure how ##__REGISTRY_HANDLER_END__ can really help. That doesn't mean
that we should try to help to make things easier, especially for those who
wrote the well structured code in first place. But for the latter it
should be very easy to do that anyway.
But what problem are we trying to solve here? The only problem I know of
is the closure effect, which happens when we wrap subs inside the
handler() sub. Or do you try to solve something else?
> > this custom parse() function can be always provided and used if wanted
> > instead of the default one, rather than complicating the parsing of the
> > default sub.
>
> Don't care about adding minor complication to that parser, myself, since
> the users never have to read it and, unless you do something non-minor,
> the performance hit won't be noticable except when stat()ing each time,
> and then the time taken to stat() and to recompile the resulting perl
> code will swamp the extra parse time, and the admin is specifically
> asking to be lower performance and developer-friendly anyway in that
> case. But I agree the parser should only be complexified for good
> reason, like if ##__REGISTRY_HANDLER__ is deemed useful.
That shouldn't be a problem. If we design this system as flexible as
possible, we can try to provide a new handler which does what you suggest
and then if it works well and doesn't add a big overhead, than we can
replace the previous one with the latter one. Adding
##__REGISTRY_HANDLER__ shouldn't add any overhead at all, but that's only
in case where the script is preloaded.
> > > - A source filter, to allow burgeoning young mod_perl hackers to
> > > develop their radical new idea (ie a new templating system) easily.
> > > This is probably best done as an overridable method like
> > > parse_source(). The base class parse_source would (in my perfect,
> > > little world) parse the source for the ##__BEGIN__HANDLER, __END__,
> > > __DATA__, etc. tokens and pass the resulting chunks to the little
> > > templating engine needed to do the following...
> >
> > Yup, just like your previous idea. write your own parse_source() and do
> > whatever you want.
>
> Well, not quite; the previous idea is not about what I'd want, it's
> about a specific feature that might make it easier to tweak CGI
> scripts to run under Apache::Registry. This one's about making
> Apache::Registry pervertable ;-). The former's an idea for a built in
> feature, the latter is for built in extensibility.
Yup, but the answer doesn't change. You are free to provide a new
parse_source and gen_code (as you explain later) and it should just work.
The only thing we should make sure is think well and put all the hooks
that we might need in the future (of course we can add these later as
well), then these hooks can be used with any custom code, therefore source
filters shouldn't be a problem at all.
The whole system is pretty much looking like Apache request cycle where we
register some hook to do something. The only difference is that we allow
only one hook per single phase. Or do you think you may want to run a few
different hooks and make it really like Apache hooks, where each hook
decides whether it wants to handle the current phase or not? I think that
would slow things down, since we will need to provide the whole mechanism
with calls.
> > :) this will be possible as well.
> >
> > > This would turn Apache::Registry in to a templating system backend
> > > and/or a custom application framework, whereby I could use Perl files
> > > ("scripts") instead of template files.
> >
> > Yup. Also check Apache::Template!
>
> Umm, that's not it at all; that's a prebuilt handler to call tt2. What
> I'm suggesting is more like taking the current proposed model of:
>
> cgiscript -> $code = parse_source() -> gen_code( $code ) -> eval
>
> $code is the body of the handler: "use CGI ; ...."
>
> and making $code be a HASH so parse_source()+gen_code() can do some
> rearranging and so extra values (like source file name and mtime)
> can be passed in to gen_code(); and making gencode by default be a very
> simple application of a template to the passed-in HASH:
>
> cgiscript -> $hash = parse_source() -> gen_code( $hash ) -> eval
>
> $hash is { fn => "...", global_code => "...", code => "..." }
>
> . gen_code() takes $hash and join()s it, just like the above gen_code()
> takes $code and join()s it.
>
> I'm taking it just a step further and proposing that gen_code()'s join()
> be built by compiling a simple template in to a join(). I've done this
> before as an experiment to see how small and fast a templating system
> could go without dipping in to C code; it produces small, fast code
> compared to techniques found on CPAN. That's not important in the
> average templating situation, so I haven't foisted it on the world, but
> it does demonstrate that a sub like gen_code can be a converted template
> and be *exactly* as fast as hand-written join().
I guess I'm not very clear on what you are trying to accomplish. the
template you are talking about will look something like that?
<FILENAME>: foobar</FILENAME>
<GLOBALCODE>
code here
</GLOBALCODE>
<HANDLERCODE>
the code that will be wrapped into sub handler {}
</HANDLERCODE>
I'm probably on the wrong track and if I do please give me a short example
of the template you are talking about. But if I'm on the right track, why
not to write a plain handler in first place?
> So, there would be no speed hit; there would be no memory hit unless a
> non-standard template is used (the template converter could be lazily
> loaded, and the default gen_code template can be pre-compiled to Perl
> code before distribution; and Apache::Registry gets more flexible.
>
> I'm not trying to replace or use something like Apache::Template; if it
> sounds like I am than I've not been clear enough. I think using the
> hash passing and an overloadable gen_code() might be the optimal
> suggestion, the templating approach would be really nice if lots of
> people wanted to customize gen_code(), but I don't think a lot of people
> do; just letting it be overridden is enough...
>
> > I'd like to hear more ideas about solving the closure problem (in addition
> > to the one you've suggested with ##__APACHE__HANLER__.
>
> So would Larry and perl5-porters, I'm sure...
:(
It's different for p5p, because you can avoid writing code that creates
undesirable effects. I don't think this is a problem for p5p, since
the closure effect is a feature. This is not a situation with
Apache::Registry, where this happens as an undesired side-effect in most
cases.
> 'nuther issue: what's the plan to make it threaded-MPM compatible given
> that it does a chdir() and calls
Hmm, I really have to start digging into the threading issues, I've
ignored them so far. Is chdir() not thread-safe? If you chdir in one
thread, does it affect other threads? Also what other calls you are
talking about?
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Sat, Sep 08, 2001 at 05:41:12PM +0800, Stas Bekman wrote:
> On Fri, 7 Sep 2001, Barrie Slaymaker wrote:
>
> > On Fri, Sep 07, 2001 at 04:56:30PM +0800, Stas Bekman wrote:
>
> It won't be too confusing for most of the people since they will just use
> Apache::Registry or Apache::PerlRun as before, without even knowing that
> these are not real modules anymore.
Figured such "passive use" would be backward compatible, the custom
directives should allow for slight tweaking without having to think of
cooking or subclassing.
I'm still pondering whether the complexity of cooking is worth the minor
speed improvement; it's a really elegant approach to hyper-optimizing,
but the few extra conditionals that cooking optimizes away will be
extremely minor compared with both (A) the speedup of using
Apache::Registry in the first place and (B) the speed of the script. I
think the performance benefits will be swamped by the other parts of the
system. But if it's really simple to implement, I see no problem with
it. It is a neat technical approach.
> > For instance, setting root of the namespace the script/handler is
> > compiled in to and the algorithm used to generate the relative part of
> > the namespace should be able to be set by a parameter. That might be
> > configured using perlish interpolation:
> >
> > PerlRegistryNameSpace MyRegistryRoot::${filename}
> >
> > where $filename/$inode/$uri/$vh is escaped to be a nice package name.
> > This leads to the natural
> >
> > PerlRegistryNameSpace MyRegistryRoot::${vh}::${filename}
> >
> > and the slightly unnatural:
> >
> > PerlRegistryNameSpace MyRegistryRoot::&{My::key_generating_sub}
> >
> > or:
> >
> > PerlRegistryNameSpace &{My::key_generating_sub}
> >
> > to allow some subroutine to be called to generate the name.
>
> I think that all directives in httpd.conf or cook() should accept a
> reference to a sub, so you can write any sub anywhere and use it. One of
> the most important benefits of it is using NOPs.
>
> package Foo;
> use constant NOP => sub {};
>
> now is it really getting optimized away at compile time?
Depends on how you use it. Do you intend to do something like having
PerlRegistryDoStat Foo::NOP cause a cooked package to do something like
*do_stat = *Foo::NOP ;
...some lines later...
$mtime = (do_stat($filename))[9];
? I think that'll barf due to passing in a parameter to a sub with a ()
prototype:
$ perl -we "sub NOP(){};NOP('a')"
Too many arguments for main::NOP at -e line 1, at end of line
Execution of -e aborted due to compilation errors.
Perhaps better for httpd.conf readability to use a special value of
"Off" to force a NOP, "On" for default operation, and "SubName" to cook
code like:
use constant get_mtime => "" ;
...some lines later....
my $mtime ;
$mtime = lc get_mtime eq "On" ? (stat $fn)[9] : get_mtime->()
if get_mtime && lc get_mtime ne "off" ;
That rather complex expression should optimize away nicely for /off/i ;
Or did I misunderstand your intent?
> Or is there some better way to make NOP CODE reference?
I don't think there's a really good way to do a NOP code ref. Of course
you could pass the filename in a global to avoid the prototype vs. arg.
passing issue, but that's a tad messy.
> > It'd be nice if the new Apache::Registry could use or just cooperate
> > with Apache::Reload for autostat/autoreload.
>
> That won't really work. Because the files on the disk aren't the same as
> registry packages, unless Apache::Reload will try to use a known interface
> to package_reload in the registry space, but I see no why how
> Apache::Reload will figure out what registry package in %INC belongs to
> what Apache::RegistryFoo module.
Not sure it will out of the gate, but either tweaking Apache::Reload to
know about files so
use Apache::Reload "/path/to/perlrun/script" ;
would DWIM (analogous to require "/path/to/perllib" vs. require Module).
Or a subclass of Apache::Reload, altering package_to_module()'s
behavior. Making Apache::Reload more flexible would be a good thing.
> Hmm, that's an interesting idea. But won't it confuse users even more?
> this will require them to move all the none-handler code up, or we need
> something like: ##__REGISTRY_HANDLER_END__ as well.
My experience is that most CGI scripts require munging to run nicely
under Apache::Registry anyway, but YMMV. Just looking to make the
munging easier.
> this custom parse() function can be always provided and used if wanted
> instead of the default one, rather than complicating the parsing of the
> default sub.
Don't care about adding minor complication to that parser, myself, since
the users never have to read it and, unless you do something non-minor,
the performance hit won't be noticable except when stat()ing each time,
and then the time taken to stat() and to recompile the resulting perl
code will swamp the extra parse time, and the admin is specifically
asking to be lower performance and developer-friendly anyway in that
case. But I agree the parser should only be complexified for good
reason, like if ##__REGISTRY_HANDLER__ is deemed useful.
> > - A source filter, to allow burgeoning young mod_perl hackers to
> > develop their radical new idea (ie a new templating system) easily.
> > This is probably best done as an overridable method like
> > parse_source(). The base class parse_source would (in my perfect,
> > little world) parse the source for the ##__BEGIN__HANDLER, __END__,
> > __DATA__, etc. tokens and pass the resulting chunks to the little
> > templating engine needed to do the following...
>
> Yup, just like your previous idea. write your own parse_source() and do
> whatever you want.
Well, not quite; the previous idea is not about what I'd want, it's
about a specific feature that might make it easier to tweak CGI scripts to run
under Apache::Registry. This one's about making Apache::Registry
pervertable ;-). The former's an idea for a built in feature, the
latter is for built in extensibility.
> :) this will be possible as well.
>
> > This would turn Apache::Registry in to a templating system backend
> > and/or a custom application framework, whereby I could use Perl files
> > ("scripts") instead of template files.
>
> Yup. Also check Apache::Template!
Umm, that's not it at all; that's a prebuilt handler to call tt2. What
I'm suggesting is more like taking the current proposed model of:
cgiscript -> $code = parse_source() -> gen_code( $code ) -> eval
$code is the body of the handler: "use CGI ; ...."
and making $code be a HASH so parse_source()+gen_code() can do some
rearranging and so extra values (like source file name and mtime)
can be passed in to gen_code(); and making gencode by default be a very
simple application of a template to the passed-in HASH:
cgiscript -> $hash = parse_source() -> gen_code( $hash ) -> eval
$hash is { fn => "...", global_code => "...", code => "..." }
. gen_code() takes $hash and join()s it, just like the above gen_code()
takes $code and join()s it.
I'm taking it just a step further and proposing that gen_code()'s join()
be built by compiling a simple template in to a join(). I've done this
before as an experiment to see how small and fast a templating system
could go without dipping in to C code; it produces small, fast code
compared to techniques found on CPAN. That's not important in the
average templating situation, so I haven't foisted it on the world, but
it does demonstrate that a sub like gen_code can be a converted template
and be *exactly* as fast as hand-written join().
So, there would be no speed hit; there would be no memory hit unless a
non-standard template is used (the template converter could be lazily
loaded, and the default gen_code template can be pre-compiled to Perl
code before distribution; and Apache::Registry gets more flexible.
I'm not trying to replace or use something like Apache::Template; if it
sounds like I am than I've not been clear enough. I think using the
hash passing and an overloadable gen_code() might be the optimal
suggestion, the templating approach would be really nice if lots of
people wanted to customize gen_code(), but I don't think a lot of people
do; just letting it be overridden is enough...
> I'd like to hear more ideas about solving the closure problem (in addition
> to the one you've suggested with ##__APACHE__HANLER__.
So would Larry and perl5-porters, I'm sure...
'nuther issue: what's the plan to make it threaded-MPM compatible given
that it does a chdir() and calls
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Fri, 7 Sep 2001, Barrie Slaymaker wrote:
> On Fri, Sep 07, 2001 at 04:56:30PM +0800, Stas Bekman wrote:
> > This is a proposal paper for Apache::Registry for mod_perl 2.0.
> >
> > The whole family of Apache::Registry-like modules can be transformed
> > from hardcoded packages with specified functionality into a what I
> > call Apache::Registry::Cooker packages.
> >
> > Since various users will want various behavior from various registry
> > modules, it'll be too cumbersome to create and maintain all possible
> > variations. Of course this could be implemented as a sub-classable
> > system, where users wishing their own behavior, need to subclass
> > whichever existing module whose behavior is the closest to the desired
> > one. I believe that compiling the registry package on the fly will
> > make things more flexible.
> >
> > So I suggest the following spec:
> >
> > Apache::Registry::Cooker - cook the desired registry handler.
> >
> > e.g. put in startup.pl:
>
>
> Or the repurposed <Perl>?
Yup, that's exactly why I came up with this idea :0)
> > use Apache::Registry::Cooker;
> > Apache::Registry::Cooker::cook
> > ({
> > package => 'MyCoolRegistry',
> > key_alg => 'filename', # (or inode, or uri, or vh+uri, ...)
> > stat_src => 1, (0 not to stat on each request)
> > flush => 0, # flush namespace on each request
> > ... # more features to come
> > });
>
> Howabout custom directives, so no startup.pl needed, and can use
> different settings in different <Location>, <Directory>, <Proxy>,
> whatever (these 4 correspond to your 4 examples, playing the name game a
> bit):
>
> PerlRegistryPackage MyCoolRegistry
> PerlRegistryKeyAlg filename
> PerlRegistryAutoReload 1
> PerlRegistryFlush 0
That won't be a problem. We can provide 3 different ways to cook packages:
1. manually crafting the package.
2. via cook() API.
3. via custom directives.
> Hmmm, also might want to allow key_alg/PerlRegistryKeyAlg to take a
> handler spec:
>
> PerlRegistryKeyAlg My::NameSpaceGenerator
>
> These would all be read by Apache::Registry::handler(). I don't think
> we need a new class cooked up for each of these, that seems likely to be
> too confusing.
It won't be too confusing for most of the people since they will just use
Apache::Registry or Apache::PerlRun as before, without even knowing that
these are not real modules anymore.
> What's more important to me is controlling the parameters of
> Apache::Registry, or subclassing it when I get too far away from it's
> noremal capabilities.
You should be able to subclass the resulting packages.
> For instance, setting root of the namespace the script/handler is
> compiled in to and the algorithm used to generate the relative part of
> the namespace should be able to be set by a parameter. That might be
> configured using perlish interpolation:
>
> PerlRegistryNameSpace MyRegistryRoot::${filename}
>
> where $filename/$inode/$uri/$vh is escaped to be a nice package name.
> This leads to the natural
>
> PerlRegistryNameSpace MyRegistryRoot::${vh}::${filename}
>
> and the slightly unnatural:
>
> PerlRegistryNameSpace MyRegistryRoot::&{My::key_generating_sub}
>
> or:
>
> PerlRegistryNameSpace &{My::key_generating_sub}
>
> to allow some subroutine to be called to generate the name.
I think that all directives in httpd.conf or cook() should accept a
reference to a sub, so you can write any sub anywhere and use it. One of
the most important benefits of it is using NOPs.
package Foo;
use constant NOP => sub {};
now is it really getting optimized away at compile time? Or is there some
better way to make NOP CODE reference?
and then saying:
PerlRegistryDoStat Foo::NOP
to skip the stat() call.
So when handler() calls do_stat, it'll be optimized away at compile time.
Am I on the right track?
> It'd be nice if the new Apache::Registry could use or just cooperate
> with Apache::Reload for autostat/autoreload.
That won't really work. Because the files on the disk aren't the same as
registry packages, unless Apache::Reload will try to use a known interface
to package_reload in the registry space, but I see no why how
Apache::Reload will figure out what registry package in %INC belongs to
what Apache::RegistryFoo module.
> Other nice-to-have (IMHO) features
>
> - Allowing a special token in a script like ##__REGISTRY_HANDLER__
> that could be used when porting CGI scripts to move all "my" decls
> above, so that a script could be partitioned in to globals and
> handler code without having to rewrite as a handler. Perhaps the
> above template could be modified like so:
>
> package <%= $package_name %> ;
>
> ##...
>
> <%= $script_globals_section %>
>
> ##...
>
> sub handler {
> my ( $r ) = Apache::Request->new( shift ) ;
> #line 1 <%= $script_file_name %>
> {<%= $script_body_section %>} ;
> return OK ;
> }
>
> 1 ;
>
> Then, porting a script containing named subs could be "tweaked"
> by adding a comment to it like so:
>
> use CGI ;
> use DBI ;
> use strict ;
>
> my $rows ;
> my $dbh = ... ;
>
> sub emit_row {
> ++$rows ;
> print tr( map td, @_, ), "\n" ;
> }
>
> ##__REGISTRY_HANDLER__ (for Apache::Registry operation)
>
> print start_html ;
> print "<table>" ;
> print_row( @$_ ) for $dbh->selectall_arrayref(...) ;
> print "</table>" ;
> print "$rows served\n" ;
>
> that might help cgi->registry porters. Only the last 5 statements
> would end up in the handler(). Could also have other special tags
> to defer some code to a cleanup handler, but you gotta stop
> somewhere.
Hmm, that's an interesting idea. But won't it confuse users even more?
this will require them to move all the none-handler code up, or we need
something like: ##__REGISTRY_HANDLER_END__ as well.
this custom parse() function can be always provided and used if wanted
instead of the default one, rather than complicating the parsing of the
default sub.
> - A source filter, to allow burgeoning young mod_perl hackers to
> develop their radical new idea (ie a new templating system) easily.
> This is probably best done as an overridable method like
> parse_source(). The base class parse_source would (in my perfect,
> little world) parse the source for the ##__BEGIN__HANDLER, __END__,
> __DATA__, etc. tokens and pass the resulting chunks to the little
> templating engine needed to do the following...
Yup, just like your previous idea. write your own parse_source() and do
whatever you want.
> - specify the module file generated from a script as a subroutine
> template file, so I/you/we could define an application-specific
> template like (borrowing ASP tags here):
>
> package <%= $package_name %> ;
>
> use strict ; ## or not...
> use My::Standard::Lib ;
> use Apache::Util ;
> use Apache::File ;
> use Apache::Constant ;
> use My::Application::Lib ;
> use GD ;
>
> *dbh = *My::Globals::dbh ;
>
> ## etc., etc.
>
> use base qw( My::AppBase ) ;
>
> ## Some little utility routines...
> sub empty { ! defined $_[0] || ! length $_[0] }
> ## etc.
>
> sub handler {
> my ( $r ) = Apache::Request->new( shift ) ;
> #line 1 <%= $script_file_name %>
> {<%= $script_body %>} ;
> return OK ;
> }
>
> 1 ;
>
> This could be done a little less clearly by using a overloadable
> Apache::Registry method to return the source code to be eval()ed,
> but lately I've been finding that templates work their magic when
> writing Perl and C code generators just as well as when writing
> HTML or RTF code generators. For instance, you could easily call
> $r->dir_config in your nifty little registry module template. Don't
> want to start a debate on tempalting engines though, so just being
> able to override a method to convert script source code in to
> handler() module source code would be nice.
:) this will be possible as well.
> This would turn Apache::Registry in to a templating system backend
> and/or a custom application framework, whereby I could use Perl files
> ("scripts") instead of template files.
Yup. Also check Apache::Template!
Thanks for the useful comments, Barrie
I'd like to hear more ideas about solving the closure problem (in addition
to the one you've suggested with ##__APACHE__HANLER__.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: RFC: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Fri, Sep 07, 2001 at 04:56:30PM +0800, Stas Bekman wrote:
> This is a proposal paper for Apache::Registry for mod_perl 2.0.
>
> The whole family of Apache::Registry-like modules can be transformed
> from hardcoded packages with specified functionality into a what I
> call Apache::Registry::Cooker packages.
>
> Since various users will want various behavior from various registry
> modules, it'll be too cumbersome to create and maintain all possible
> variations. Of course this could be implemented as a sub-classable
> system, where users wishing their own behavior, need to subclass
> whichever existing module whose behavior is the closest to the desired
> one. I believe that compiling the registry package on the fly will
> make things more flexible.
>
> So I suggest the following spec:
>
> Apache::Registry::Cooker - cook the desired registry handler.
>
> e.g. put in startup.pl:
Or the repurposed <Perl>?
> use Apache::Registry::Cooker;
> Apache::Registry::Cooker::cook
> ({
> package => 'MyCoolRegistry',
> key_alg => 'filename', # (or inode, or uri, or vh+uri, ...)
> stat_src => 1, (0 not to stat on each request)
> flush => 0, # flush namespace on each request
> ... # more features to come
> });
Howabout custom directives, so no startup.pl needed, and can use
different settings in different <Location>, <Directory>, <Proxy>,
whatever (these 4 correspond to your 4 examples, playing the name game a
bit):
PerlRegistryPackage MyCoolRegistry
PerlRegistryKeyAlg filename
PerlRegistryAutoReload 1
PerlRegistryFlush 0
Hmmm, also might want to allow key_alg/PerlRegistryKeyAlg to take a
handler spec:
PerlRegistryKeyAlg My::NameSpaceGenerator
These would all be read by Apache::Registry::handler(). I don't think
we need a new class cooked up for each of these, that seems likely to be
too confusing.
What's more important to me is controlling the parameters of
Apache::Registry, or subclassing it when I get too far away from it's
noremal capabilities.
For instance, setting root of the namespace the script/handler is
compiled in to and the algorithm used to generate the relative part of
the namespace should be able to be set by a parameter. That might be
configured using perlish interpolation:
PerlRegistryNameSpace MyRegistryRoot::${filename}
where $filename/$inode/$uri/$vh is escaped to be a nice package name.
This leads to the natural
PerlRegistryNameSpace MyRegistryRoot::${vh}::${filename}
and the slightly unnatural:
PerlRegistryNameSpace MyRegistryRoot::&{My::key_generating_sub}
or:
PerlRegistryNameSpace &{My::key_generating_sub}
to allow some subroutine to be called to generate the name.
It'd be nice if the new Apache::Registry could use or just cooperate
with Apache::Reload for autostat/autoreload.
Other nice-to-have (IMHO) features
- Allowing a special token in a script like ##__REGISTRY_HANDLER__
that could be used when porting CGI scripts to move all "my" decls
above, so that a script could be partitioned in to globals and
handler code without having to rewrite as a handler. Perhaps the
above template could be modified like so:
package <%= $package_name %> ;
##...
<%= $script_globals_section %>
##...
sub handler {
my ( $r ) = Apache::Request->new( shift ) ;
#line 1 <%= $script_file_name %>
{<%= $script_body_section %>} ;
return OK ;
}
1 ;
Then, porting a script containing named subs could be "tweaked"
by adding a comment to it like so:
use CGI ;
use DBI ;
use strict ;
my $rows ;
my $dbh = ... ;
sub emit_row {
++$rows ;
print tr( map td, @_, ), "\n" ;
}
##__REGISTRY_HANDLER__ (for Apache::Registry operation)
print start_html ;
print "<table>" ;
print_row( @$_ ) for $dbh->selectall_arrayref(...) ;
print "</table>" ;
print "$rows served\n" ;
that might help cgi->registry porters. Only the last 5 statements
would end up in the handler(). Could also have other special tags
to defer some code to a cleanup handler, but you gotta stop
somewhere.
- A source filter, to allow burgeoning young mod_perl hackers to
develop their radical new idea (ie a new templating system) easily.
This is probably best done as an overridable method like
parse_source(). The base class parse_source would (in my perfect,
little world) parse the source for the ##__BEGIN__HANDLER, __END__,
__DATA__, etc. tokens and pass the resulting chunks to the little
templating engine needed to do the following...
- specify the module file generated from a script as a subroutine
template file, so I/you/we could define an application-specific
template like (borrowing ASP tags here):
package <%= $package_name %> ;
use strict ; ## or not...
use My::Standard::Lib ;
use Apache::Util ;
use Apache::File ;
use Apache::Constant ;
use My::Application::Lib ;
use GD ;
*dbh = *My::Globals::dbh ;
## etc., etc.
use base qw( My::AppBase ) ;
## Some little utility routines...
sub empty { ! defined $_[0] || ! length $_[0] }
## etc.
sub handler {
my ( $r ) = Apache::Request->new( shift ) ;
#line 1 <%= $script_file_name %>
{<%= $script_body %>} ;
return OK ;
}
1 ;
This could be done a little less clearly by using a overloadable
Apache::Registry method to return the source code to be eval()ed,
but lately I've been finding that templates work their magic when
writing Perl and C code generators just as well as when writing
HTML or RTF code generators. For instance, you could easily call
$r->dir_config in your nifty little registry module template. Don't
want to start a debate on tempalting engines though, so just being
able to override a method to convert script source code in to
handler() module source code would be nice.
This would turn Apache::Registry in to a templating system backend
and/or a custom application framework, whereby I could use Perl files
("scripts") instead of template files.
- Barrie
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Fri, 21 Sep 2001, Barrie Slaymaker wrote:
> On Tue, Sep 18, 2001 at 12:44:37AM +0800, Stas Bekman wrote:
> > Ken Williams wrote:
> >
> > > Stas Bekman <st...@stason.org> wrote:
> > >
> > >> On Sat, 8 Sep 2001, raptor wrote:
> > >>
> > >>> my $eval = join ( '', qq{
> > >>> package $package;
> > >>> my $request;
> > >>> START:
> > >>> use Apache qw(exit);
> > >>> $usercode
> > >>> sub handler {
> > >>> $package::request = \$r;
> > >>> goto START;
> > >>> };
> > >>> };
> > >>
> > >>
> > >> Hmm, that's an interesting idea. goto() can be very useful at times,
> > >> even if it's considered evil. Your solution seems to be too easy :)
> > >> Gotta go to sleep on it and see if there are some hidden issues with it.
>
> Any luck playing with this?
Not yet, got carried away with other stuff.
> I tried this a while ago on that weird experimental templating system I
> was nattering on about. Couldn't get it to work in 5.6.0 when compiling
> a package; START couldn't be found after the flow of control exited the
> program. I guess that the source code of the module gets disposed of,
> rendering START unreachable. Hopefully I missed a trick and y'all have
> it figured out...
It's quite possible that it doesn't work. But we can use then:
goto &NAME
The "goto-&NAME" form is quite different from the
other forms of "goto". In fact, it isn't a goto
in the normal sense at all, and doesn't have the
stigma associated with other gotos. Instead, it
substitutes a call to the named subroutine for the
currently running subroutine. This is used by
"AUTOLOAD" subroutines that wish to load another
subroutine and then pretend that the other subrou
tine had been called in the first place (except
that any modifications to @_ in the current sub
routine are propagated to the other subroutine.)
After the "goto", not even "caller" will be able
to tell that this routine was called first.
NAME needn't be the name of a subroutine; it can
be a scalar variable containing a code reference,
or a block which evaluates to a code reference.
which is even cooler :)
> P.S. A belated huge congrats on your ticketmaster.com gig. Wow. Too
> cool.
Thanks a lot, It's too cool indeed!
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Barrie Slaymaker <ba...@slaysys.com>.
On Tue, Sep 18, 2001 at 12:44:37AM +0800, Stas Bekman wrote:
> Ken Williams wrote:
>
> > Stas Bekman <st...@stason.org> wrote:
> >
> >> On Sat, 8 Sep 2001, raptor wrote:
> >>
> >>> my $eval = join ( '', qq{
> >>> package $package;
> >>> my $request;
> >>> START:
> >>> use Apache qw(exit);
> >>> $usercode
> >>> sub handler {
> >>> $package::request = \$r;
> >>> goto START;
> >>> };
> >>> };
> >>
> >>
> >> Hmm, that's an interesting idea. goto() can be very useful at times,
> >> even if it's considered evil. Your solution seems to be too easy :)
> >> Gotta go to sleep on it and see if there are some hidden issues with it.
Any luck playing with this?
I tried this a while ago on that weird experimental templating system I
was nattering on about. Couldn't get it to work in 5.6.0 when compiling
a package; START couldn't be found after the flow of control exited the
program. I guess that the source code of the module gets disposed of,
rendering START unreachable. Hopefully I missed a trick and y'all have
it figured out...
- Barrie
P.S. A belated huge congrats on your ticketmaster.com gig. Wow. Too
cool.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
Ken Williams wrote:
> Stas Bekman <st...@stason.org> wrote:
>
>> On Sat, 8 Sep 2001, raptor wrote:
>>
>>> my $eval = join ( '', qq{
>>> package $package;
>>> my $request;
>>> START:
>>> use Apache qw(exit);
>>> $usercode
>>> sub handler {
>>> $package::request = \$r;
>>> goto START;
>>> };
>>> };
>>
>>
>> Hmm, that's an interesting idea. goto() can be very useful at times,
>> even if it's considered evil. Your solution seems to be too easy :)
>> Gotta go to sleep on it and see if there are some hidden issues with it.
>
>
> I usually like to use a labeled 'next' or 'last' instead of the 'goto':
>
> my $eval = qq{
> package $package;
> my $request;
> REQUEST: {
> use Apache qw(exit);
> $usercode
> sub handler {
> $package::request = \$r;
> next REQUEST;
> }
> }
> };
>
> (I haven't followed this thread, so I don't know what the larger problem
> is that you're solving.)
That's the root of the problem -- we are trying to solve the problem
with nested named subroutines which create the closure effect. So as
long as you create a block we get back to the same point we started from :
sub handler{} that wraps everything into a block :)
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Ken Williams <ke...@forum.swarthmore.edu>.
Stas Bekman <st...@stason.org> wrote:
> On Sat, 8 Sep 2001, raptor wrote:
>> my $eval = join ( '', qq{
>> package $package;
>> my $request;
>> START:
>> use Apache qw(exit);
>> $usercode
>> sub handler {
>> $package::request = \$r;
>> goto START;
>> };
>> };
>
> Hmm, that's an interesting idea. goto() can be very useful at times,
> even if it's considered evil. Your solution seems to be too easy :)
> Gotta go to sleep on it and see if there are some hidden issues with it.
I usually like to use a labeled 'next' or 'last' instead of the 'goto':
my $eval = qq{
package $package;
my $request;
REQUEST: {
use Apache qw(exit);
$usercode
sub handler {
$package::request = \$r;
next REQUEST;
}
}
};
(I haven't followed this thread, so I don't know what the larger problem
is that you're solving.)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Sat, 8 Sep 2001, raptor wrote:
> | > use something like this :
> | >
> | > my $eval = join ( '', qq{
> | > package $package;
> | > use Apache qw(exit);
> | > $sub
> | > sub handler {
> | > $line
> | > $subname($r);
> | > };
> | > };
> | >
> | > just of my head... may have error.. or may don't work at all..
> |
> | what's $subname? you mean wrapping all the code into a sub and then
> | calling in? but that's exactly what's handler() doing. It doesn't change
> | anything, unless I didn't understand your proposal.
>
> ]- whatever.. but i see now that it is not worth-it... my idea was to get
> the user script outside of the handler() ...
> but what if we do this :
>
> my $eval = join ( '', qq{
> package $package;
> my $request;
> START:
> use Apache qw(exit);
> $usercode
> sub handler {
> $package::request = \$r;
> goto START;
> };
> };
>
> what other problems can arise !??
Hmm, that's an interesting idea. goto() can be very useful at times, even
if it's considered evil. Your solution seems to be too easy :) Gotta go to
sleep on it and see if there are some hidden issues with it.
I think you've missed the return status though, but this is easy to fix.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by raptor <ra...@unacs.bg>.
| > use something like this :
| >
| > my $eval = join ( '', qq{
| > package $package;
| > use Apache qw(exit);
| > $sub
| > sub handler {
| > $line
| > $subname($r);
| > };
| > };
| >
| > just of my head... may have error.. or may don't work at all..
|
| what's $subname? you mean wrapping all the code into a sub and then
| calling in? but that's exactly what's handler() doing. It doesn't change
| anything, unless I didn't understand your proposal.
]- whatever.. but i see now that it is not worth-it... my idea was to get
the user script outside of the handler() ...
but what if we do this :
my $eval = join ( '', qq{
package $package;
my $request;
START:
use Apache qw(exit);
$usercode
sub handler {
$package::request = \$r;
goto START;
};
};
what other problems can arise !??
=====
iVAN
raptor@unacs.bg
=====
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by Stas Bekman <st...@stason.org>.
On Sat, 8 Sep 2001, raptor wrote:
> | * __DATA__ and __END__ tokens: should read the file till these tokens
> | are met and compile only the code that has been read so far.
> ]- I'm not aware of the whole process of how Apache::Registry works, but can
> we just do this :
>
> Apache::Registry
> ===========
> ....
> my $sub = $r->slurp_filename;
> $sub =~ s/^(.*?)(__END__|__DATA__)\n.*$/$1/;
> .....
sure, but this is expensive if you don't do that at startup. I'm not sure
if reading line by line util /^(__END__|__DATA)/ is reached would be
faster though. need to benchmark, but even then it'll probably depend on
the size of the source file that gets parsed.
> One more thing about closures instead of :
> .....
> my $eval = join ( '', qq{
> package $package;
> use Apache qw(exit);
> sub handler {
> $line
> $sub
> };
> };
>
>
> use something like this :
>
> my $eval = join ( '', qq{
> package $package;
> use Apache qw(exit);
> $sub
> sub handler {
> $line
> $subname($r);
> };
> };
>
> just of my head... may have error.. or may don't work at all..
what's $subname? you mean wrapping all the code into a sub and then
calling in? but that's exactly what's handler() doing. It doesn't change
anything, unless I didn't understand your proposal.
_____________________________________________________________________
Stas Bekman JAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide http://perl.apache.org/guide
mailto:stas@stason.org http://apachetoday.com http://eXtropia.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org
Re: Apache::Registry family re-design
Posted by raptor <ra...@unacs.bg>.
| * __DATA__ and __END__ tokens: should read the file till these tokens
| are met and compile only the code that has been read so far.
]- I'm not aware of the whole process of how Apache::Registry works, but can
we just do this :
Apache::Registry
===========
....
my $sub = $r->slurp_filename;
$sub =~ s/^(.*?)(__END__|__DATA__)\n.*$/$1/;
.....
One more thing about closures instead of :
.....
my $eval = join ( '', qq{
package $package;
use Apache qw(exit);
sub handler {
$line
$sub
};
};
use something like this :
my $eval = join ( '', qq{
package $package;
use Apache qw(exit);
$sub
sub handler {
$line
$subname($r);
};
};
just of my head... may have error.. or may don't work at all..
=====
iVAN
raptor@unacs.bg
=====
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org