I'm trying to resolve two related items in todo/release: ------------------ some autogenerated record accessors shouldn't be get/set but only get (e.g. Apache->server->is_virtual(1) is wrong). Need to add a new flag supported by MapUtil and map files, where we can say which accessors should be read-only
Apache::{Server,Process} classes: require mutex lock for writing (e.g. $s->(error_fname|error_log) Status: most likely some server/process datastructures aren't supposed to be modified at request time. So instead of mutex locking, we think we should simply have a flag that will be down during the startup and will allow methods modifying $s/$proc structs (the method will check that flag and if it's up it'll die). At the beginning of child_init it'll raise the flag and lower it at the end of child_exit. ------------------
The first step: provide support for read-only structure accessors,
made all perl server_rec and process_rec accessors read-only (the patch is below).
When applying the change the test suite breaks on the following:
- t/response/TestAPI/aplog.pm:65 $s->loglevel(Apache::LOG_INFO);
- t/response/TestCompat/apache.pm:65 $r->server->server_admin($admin);
I don't think these should be writable, since it has the same effect as allowing 'cwd' in the multithreaded process, where one thread will affect another. All changes to the server_rec structures need to be done after the config and before the child_init phase. process_rec could be modified during the child_init phase, but I don't think anybody will want to modify the process_rec struct at all.
On the other hand during the request one can call add_config() and modify things like ServerAdmin as in t/response/TestCompat/apache.pm:
my $admin = $r->server->server_admin; Apache->httpd_conf('ServerAdmin [EMAIL PROTECTED]'); ok t_cmp('[EMAIL PROTECTED]', $r->server->server_admin, 'Apache->httpd_conf'); $r->server->server_admin($admin);
So if Apache allows doing that and is not concerned about mutexing the modification of the server_admin field, then it's a bug in Apache and should be addressed by httpd-dev. If they provide the mutexing, we can then re-use it for mutexing r/w process/server accessors.
If we do need to support mutexed r/w accessors then we will change TypeMap.pm and WrapXS.pm to support a new accessor type (@?) similar to my extension of the maps/*_structures.map '<' to allow read-only accessors.
Also it's may be an idea to support r/w server accessors only for those records that can be modified via add_config(), e.g. ServerAdmin.
For records that we aren't sure about making r/w, we should make them read-only, since we can always re-enable that back after 2.0 API is frozen. It shouldn't affect anybody.
Here is the patch:
Index: lib/ModPerl/MapUtil.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/MapUtil.pm,v retrieving revision 1.3 diff -u -r1.3 MapUtil.pm --- lib/ModPerl/MapUtil.pm 26 Aug 2001 03:38:27 -0000 1.3 +++ lib/ModPerl/MapUtil.pm 9 Feb 2004 20:35:36 -0000 @@ -11,6 +11,7 @@
our @ISA = qw(Exporter);
+# '<' => 'auto-generated but gives only a read-only access' my %disabled_map = ( '!' => 'disabled or not yet implemented', '~' => 'implemented but not auto-generated', Index: lib/ModPerl/StructureMap.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/StructureMap.pm,v retrieving revision 1.3 diff -u -r1.3 StructureMap.pm --- lib/ModPerl/StructureMap.pm 18 Apr 2001 04:52:27 -0000 1.3 +++ lib/ModPerl/StructureMap.pm 9 Feb 2004 20:35:36 -0000 @@ -103,11 +103,18 @@ }
if (s/^(\W)\s*// or $disabled) { - $map->{$class}->{$_} = undef; - push @{ $self->{disabled}->{ $1 || '!' } }, "$class.$_"; + # < denotes a read-only accessor + if ($1 && $1 eq '<') { + $map->{$class}->{$_} = 'ro'; + } + else { + $map->{$class}->{$_} = undef; + push @{ $self->{disabled}->{ $1 || '!' } }, "$class.$_"; + } + } else { - $map->{$class}->{$_} = 1; + $map->{$class}->{$_} = 'rw'; } }
Index: lib/ModPerl/TypeMap.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/TypeMap.pm,v retrieving revision 1.18 diff -u -r1.18 TypeMap.pm --- lib/ModPerl/TypeMap.pm 30 Dec 2002 00:27:13 -0000 1.18 +++ lib/ModPerl/TypeMap.pm 9 Feb 2004 20:35:36 -0000 @@ -275,19 +275,24 @@
return unless $class = $self->map_type($stype);
+ use Apache::TestTrace; + for my $e (@{ $struct->{elts} }) { my($name, $type) = ($e->{name}, $e->{type}); my $rtype;
- next unless $self->structure_map->{$stype}->{$name}; + # ro/rw/undef(disabled) + my $access_mode = $self->structure_map->{$stype}->{$name}; + next unless $access_mode; next unless $rtype = $self->map_type($type);
push @elts, { - name => $name, - type => $rtype, - default => $self->null_type($type), - pool => $self->class_pool($class), - class => $self->{map}->{$type} || "", + name => $name, + type => $rtype, + default => $self->null_type($type), + pool => $self->class_pool($class), + class => $self->{map}->{$type} || "", + access_mode => $access_mode, }; }
Index: lib/ModPerl/WrapXS.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/WrapXS.pm,v retrieving revision 1.65 diff -u -r1.65 WrapXS.pm --- lib/ModPerl/WrapXS.pm 9 Feb 2004 18:44:43 -0000 1.65 +++ lib/ModPerl/WrapXS.pm 9 Feb 2004 20:35:36 -0000 @@ -181,8 +181,8 @@ my $class = $struct->{class};
for my $e (@{ $struct->{elts} }) { - my($name, $default, $type) = - @{$e}{qw(name default type)}; + my($name, $default, $type, $access_mode) = + @{$e}{qw(name default type access_mode)};
(my $cast = $type) =~ s/:/_/g; my $val = get_value($e); @@ -196,7 +196,25 @@
my $attrs = $self->attrs($name);
- my $code = <<EOF; + my $code; + if ($access_mode eq 'ro') { + $code = <<EOF; +$type +$name(obj) + $class obj + +$attrs + + CODE: + RETVAL = ($cast) obj->$name; + + OUTPUT: + RETVAL + +EOF + } + elsif ($access_mode eq 'rw') { + $code = <<EOF; $type $name(obj, val=$default) $class obj @@ -217,6 +235,8 @@ RETVAL
EOF + } + push @{ $self->{XS}->{ $struct->{module} } }, { code => $code, class => $class, Index: xs/maps/apache_structures.map =================================================================== RCS file: /home/cvs/modperl-2.0/xs/maps/apache_structures.map,v retrieving revision 1.20 diff -u -r1.20 apache_structures.map --- xs/maps/apache_structures.map 9 Feb 2004 19:05:59 -0000 1.20 +++ xs/maps/apache_structures.map 9 Feb 2004 20:35:39 -0000 @@ -69,31 +69,31 @@ </request_rec>
<server_rec> - process - next +< process +< next - defn_name - defn_line_number - server_admin - server_hostname - port - error_fname - error_log - loglevel - is_virtual - module_config - lookup_defaults - addrs - timeout - keep_alive_timeout - keep_alive_max - keep_alive - path +< server_admin +< server_hostname +< port +< error_fname +< error_log +< loglevel +< is_virtual +< module_config +< lookup_defaults +< addrs +< timeout +< keep_alive_timeout +< keep_alive_max +< keep_alive +< path - pathlen - names - wild_names - limit_req_line - limit_req_fieldsize - limit_req_fields +< names +< wild_names +< limit_req_line +< limit_req_fieldsize +< limit_req_fields </server_rec>
<conn_rec> @@ -145,11 +145,11 @@ </module>
<process_rec> - pool - pconf +< pool +< pconf - argc ! argv - short_name +< short_name </process_rec>
<command_rec>
If we decide that for some server methods it's OK to be writable only before the child_init phase, we could use a new flag introduced by the below patch: STRUCT_READ_ONLY
Index: lib/ModPerl/Code.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v
retrieving revision 1.115
diff -u -r1.115 Code.pm
--- lib/ModPerl/Code.pm 9 Feb 2004 18:18:15 -0000 1.115
+++ lib/ModPerl/Code.pm 9 Feb 2004 20:35:35 -0000
@@ -120,7 +120,7 @@
my @ithread_opts = qw(CLONE PARENT);
my %flags = (
Srv => ['NONE', @ithread_opts, qw(ENABLE AUTOLOAD MERGE_HANDLERS),
- @hook_flags, 'UNSET'],
+ @hook_flags, qw(STRUCT_READ_ONLY UNSET)],
Dir => [qw(NONE PARSE_HEADERS SETUP_ENV MERGE_HANDLERS GLOBAL_REQUEST UNSET)],
Req => [qw(NONE SET_GLOBAL_REQUEST PARSE_HEADERS SETUP_ENV
CLEANUP_REGISTERED)],
Index: src/modules/perl/mod_perl.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
retrieving revision 1.206
diff -u -r1.206 mod_perl.c
--- src/modules/perl/mod_perl.c 10 Jan 2004 05:01:04 -0000 1.206
+++ src/modules/perl/mod_perl.c 9 Feb 2004 20:35:39 -0000
@@ -591,6 +591,21 @@
return OK;
}
+static int modperl_hook_post_config_last(apr_pool_t *pconf, apr_pool_t *plog, + apr_pool_t *ptemp, server_rec *s) +{ +#ifdef USE_ITHREADS + MP_dSCFG(s); + dTHXa(scfg->mip->parent->perl); +#endif + + /* no server_rec/process_rec modifications should be done beyond + * this point */ + MpSrvSTRUCT_READ_ONLY_On(scfg); + + return OK; +} + static int modperl_hook_create_request(request_rec *r) { MP_dRCFG; @@ -678,6 +693,9 @@
ap_hook_post_config(modperl_hook_post_config, NULL, NULL, APR_HOOK_FIRST); + + ap_hook_post_config(modperl_hook_post_config_last, + NULL, NULL, APR_HOOK_REALLY_LAST);
ap_hook_handler(modperl_response_handler, NULL, NULL, APR_HOOK_MIDDLE);
-- __________________________________________________________________ Stas Bekman JAm_pH ------> Just Another mod_perl Hacker http://stason.org/ mod_perl Guide ---> http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]