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]
