On Monday 23 April 2007 07:08, Philippe M. Chiasson wrote:
> > Is there something like $r->release_interp_after_this_phase()?
>
> Nope, but writing one would be very simple, all that's needed is
> to call
>
>   MpInterpPUTBACK_On(interp)
>

    apr_pool_cleanup_kill(r->pool, r, modperl_config_req_cleanup);
    modperl_interp_pool_set(r->pool, NULL, 0);
    interp->request=r;
    MpInterpPUTBACK_On(interp);
    MpReqCLEANUP_REGISTERED_On(rcfg);

I think this turns a per-request interpreter into a per-handler one. I have 
attached a first version of an Apache2::Interpreter module that implements 
$r->interpreter->release.

The most tricky part for me was to find the correct interp. Could you please 
have a look at that? Maybe it could be done much simpler.

Also, the cleanup stuff is buggy as it is with scope==handler. 
$r->pool->cleanup_register works by locking the interp until pool cleanup. It 
thus blocks the interp from being reused. PerlCleanupHandler does not work at 
all.

Torsten
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "mod_perl.h"
#include "mod_include.h"

typedef request_rec *Apache2__RequestRec;
typedef modperl_interp_t *Apache2__Interpreter;

static modperl_interp_t *
get_interpreter( pTHX_ request_rec *r )
{
  MP_dRCFG;
  MP_dSCFG(r->server);
  modperl_tipool_t *tipool;
  modperl_list_t *lp;
  modperl_interp_t *interp;

  if( !modperl_threaded_mpm() ) {
    return scfg->mip->parent;
  }

#ifdef USE_ITHREADS
  if( rcfg && rcfg->interp && rcfg->interp->perl==aTHX ) {
    MP_TRACE_i(MP_FUNC,
	       "get_interpreter: found interp 0x%lx in request config\n",
	       (unsigned long)rcfg->interp);
    return rcfg->interp;
  }

  if( (interp=modperl_interp_pool_get( r->pool )) &&
      interp->perl==aTHX ) {
    MP_TRACE_i(MP_FUNC,
	       "get_interpreter: found interp 0x%lx in request pool\n",
	       (unsigned long)interp);
    return interp;
  }

  if( (interp=modperl_interp_pool_get( r->connection->pool )) &&
      interp->perl==aTHX ) {
    MP_TRACE_i(MP_FUNC,
	       "get_interpreter: found interp 0x%lx in connection pool\n",
	       (unsigned long)interp);
    return interp;
  }

  if( r->main ) {
    request_rec *main_r=r->main;
    while( main_r ) {
      if( (interp=modperl_interp_pool_get( main_r->pool )) &&
	  interp->perl==aTHX ) {
	MP_TRACE_i(MP_FUNC,
		   "get_interpreter: found interp 0x%lx in connection pool\n",
		   (unsigned long)interp);
	return interp;
      }
      main_r=main_r->main;
    }
  }

  /* worst case: lock interpreter pool and loop over all busy interpreters */
  tipool=scfg->mip->tipool;
  modperl_tipool_lock(tipool);
  for( lp=tipool->busy; lp; lp=lp->next ) {
    interp=(modperl_interp_t *)(lp->data);
    if( interp && interp->perl==aTHX ) break;
  }
  modperl_tipool_unlock(tipool);

  if( interp && interp->perl==aTHX ) {
    MP_TRACE_i(MP_FUNC,
	       "get_interpreter: found interp 0x%lx in interpreter pool\n",
	       (unsigned long)interp);
    return interp;
  } else {
    MP_TRACE_i(MP_FUNC,
	       "get_interpreter: no interp found\n");
    return 0;
  }
# else	/* USE_ITHREADS */
  return 0;
# endif	/* USE_ITHREADS */
}

MODULE = Apache2::Interpreter    PACKAGE = Apache2::RequestRec

Apache2::Interpreter
interpreter(r)
    Apache2::RequestRec r
PROTOTYPE: $
CODE:
  {
    RETVAL=get_interpreter(aTHX_ r);
  }
OUTPUT:
    RETVAL

MODULE = Apache2::Interpreter    PACKAGE = Apache2::Interpreter

unsigned long
perl(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=(unsigned long)interp->perl;
  }
OUTPUT:
    RETVAL

int
num_requests(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=interp->num_requests;
  }
OUTPUT:
    RETVAL

U8
flags(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=interp->flags;
  }
OUTPUT:
    RETVAL

int
refcnt(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=interp->refcnt;
  }
OUTPUT:
    RETVAL

Apache2::RequestRec
request(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=interp->request;
  }
OUTPUT:
    RETVAL

#ifdef MP_TRACE

unsigned long
tid(interp)
    Apache2::Interpreter interp
PROTOTYPE: $
CODE:
  {
    RETVAL=interp->tid;
  }
OUTPUT:
    RETVAL

#endif

int
release(interp, r)
    Apache2::Interpreter interp
    Apache2::RequestRec r
PROTOTYPE: $
CODE:
  {
    MP_dRCFG;

    apr_pool_cleanup_kill(r->pool, r, modperl_config_req_cleanup);
    modperl_interp_pool_set(r->pool, NULL, 0);
    interp->request=r;
    MpInterpPUTBACK_On(interp);
    MpReqCLEANUP_REGISTERED_On(rcfg);

    RETVAL=0;
  }
OUTPUT:
    RETVAL

MODULE = Apache2::Interpreter

## Local Variables: ##
## mode: c ##
## End: ##

Attachment: pgpcTwrU5aAGW.pgp
Description: PGP signature

Reply via email to