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]



Reply via email to