You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Steven Siebert <sm...@gmail.com> on 2008/11/06 21:51:07 UTC

MPM-safe mp2 Singleton Pattern?

Hello,

I want to implement a singleton pattern on my logger module.  During
initial instantiation, the logger module is seeded with some
information (ie. transactionId) and creates some (ie. requestTime).
What I want is for the logger object to be instantiated (if needed)
and/or retrieved from the Logger::getInstance() method for each HTTP
request...basically I don't want to have to pass the object around but
instead return a the reference to the instance when I need it.

First, some info about my environment: mp2 on RHEL.  The prefork MPM
is in use but I explicitly turned off worker as the existing
application I will be working against is not thread safe.

What I am running into is that the new instance is created for each
process and is accessible throughout the request as intended.
Unfortunately, what I am also noticing is that when the process is
reused by Apache, the previous logger instance still exists and is
pulled back by reference and therefore have incorrect parameters
(since the transactionID and requestTime has changed).  I believe this
is by design because it obviously would give a decent performance
boost under situations where this is OK.  However, this is not one of
these times =).

I thought of two solutions, both of which don't seem a great answer.
First was to explicitly DESTROY the logger object when I was done with
the request (which would work, since I have a controller/router
managing the request).  however, if something goes wrong I can't be
sure the logger would be destroyed.  Second was to create a factory
method in addition to the traditional singleton static method to
explicitly create a new instance and overwrite the existing.  I think
this would work with my environment (only prefork MPM) but it smells
as if it wouldn't be thread safe - I imagine a spawned threat would
overwrite and corrupt multiple threads on a process.  I included
psudo-code of the second theory below so you can pretty much see what
I am doing.

Is there any way to have a MPM-safe (specifically thread-safe)
singleton pattern?

P.S.  For those of you who noticed, even though the app I'm eventually
going to integrate with is not thread safe, I am building a SOA
mid-tier that I wish to release open source and personally reuse, so I
want it to be thread safe. =)


Thanks,

Steve

psudo code:

package Logger;

my $this; # singleton instance

sub getInstance { my ( $self, $transId ) = @_;
  unless (defined $this) {
     $self->createNewInstance($transId);
  }
  return $this;
}

sub createNewInstance { my ( $self, $transId ) = @_;
  my $vars = {'transId' => $transId};
  $this = bless $vars, $self;

  $this->_getRequestDate();

  return $this;
}
1;

Re: Fwd: MPM-safe mp2 Singleton Pattern?

Posted by bharanee rathna <de...@gmail.com>.
> I couldn't get Apache::Singleton working with mp2 (used it before with no
> problems with mp1). so I switched back to Class::Singelton ...

*sigh*, 2 yr old bug report. Maybe someone should write to the
author/maintainer and take ownership ?

http://rt.cpan.org/Public/Bug/Display.html?id=19775

Easy fix though as noted in the RT ticket.  Also I think you should
turn on global request,

PerlOptions +GlobalRequest

otherwise you would not be able to get the request object via
Apache2::RequestUtil->request,. Alternatively you can set the request
object in your handler initially as Apache2->request($r);

- b

Re: Fwd: MPM-safe mp2 Singleton Pattern?

Posted by Rolf Schaufelberger <rs...@plusw.de>.
Am Freitag, 7. November 2008 19:22:56 schrieb Steven Siebert:
> Perfect!  Great info from both...exactly what I needed.  After
> Torsten's response, I theorized that I could abstract that
> functionality up and reveal a thin API for the creation/calling of
> singleton objects within a namespace in pnotes....but that seems to
> have already been done with Apache::Singleton::Request.  I'm glad I
> decided to ask the experts before attempting a hack myself.  Thanks
> guys!
>
> On Fri, Nov 7, 2008 at 1:18 PM, bharanee rathna <de...@gmail.com> wrote:
> >> The simplest way is to put the object as a pnote:
> >
> > What Torsten said, but have a look at
> >
> > http://search.cpan.org/~miyagawa/Apache-Singleton-0.07/lib/Apache/Singlet
> >on.pm
> >
> > Apache::Singleton::Request is probably what you want.

I couldn't get Apache::Singleton working with mp2 (used it before with no 
problems with mp1). so I switched back to Class::Singelton and, at the top of 
my handler (MasonX::WebApp) destroy the old instance and create a new one. I 
couldn' t find ouy why it failed with mp2 since I had not much time and my 
app had to become ready. The failure showed in a "hanging"  request.

The reason why I use Class::Singelton (and not $r->pool or $r->pnotes) is 
just, that I can reuse my perl modules in all apps running as stand alone 
scripts. So for instance , I put my DBIx;:Class schema object in there, the 
logging handler etc. 

-- 
Rolf Schaufelberger

Re: Fwd: MPM-safe mp2 Singleton Pattern?

Posted by Steven Siebert <sm...@gmail.com>.
Perfect!  Great info from both...exactly what I needed.  After
Torsten's response, I theorized that I could abstract that
functionality up and reveal a thin API for the creation/calling of
singleton objects within a namespace in pnotes....but that seems to
have already been done with Apache::Singleton::Request.  I'm glad I
decided to ask the experts before attempting a hack myself.  Thanks
guys!

On Fri, Nov 7, 2008 at 1:18 PM, bharanee rathna <de...@gmail.com> wrote:
>> The simplest way is to put the object as a pnote:
>
> What Torsten said, but have a look at
>
> http://search.cpan.org/~miyagawa/Apache-Singleton-0.07/lib/Apache/Singleton.pm
>
> Apache::Singleton::Request is probably what you want.
>

Re: Fwd: MPM-safe mp2 Singleton Pattern?

Posted by bharanee rathna <de...@gmail.com>.
> The simplest way is to put the object as a pnote:

What Torsten said, but have a look at

http://search.cpan.org/~miyagawa/Apache-Singleton-0.07/lib/Apache/Singleton.pm

Apache::Singleton::Request is probably what you want.

Re: Fwd: MPM-safe mp2 Singleton Pattern?

Posted by Torsten Foertsch <to...@gmx.net>.
On Fri 07 Nov 2008, Steven Siebert wrote:
> Is there any way to have a MPM-safe (specifically thread-safe)
> singleton pattern?

Modperl manages an interpreter pool if it runs under a threaded MPM. 
That means the first modperl-related action in the request cycle pulls 
an interpreter from the pool. Some time later the interpreter is the 
put back to the pool. The point in time when that happens is defined by 
the PerlInterpScope directive. It can happen immediately after the 
current phase in the request cycle or when the request is over or when 
the client connection is dropped. (And you can have a separate 
interpreter for a subrequest.) Perl variables allocated in one 
interpreter are accessible only from that interpreter unless they are 
marked as shared. Shared variables are implemented by the 
thread::shared module. This module creates another "shared" perl 
interpreter that does the actual memory management. A shared variable 
is then allocated inside that special interpreter and another one is 
allocated inside the current interpreter. Then that variable is "tied" 
to the variable in the shared interpreter in a similar way to what the 
tie() command does.

So for what you want you need to make sure (if I understood your 
problem) that the same instance is used throughout the request cycle. 
Plus you want that it is destroyed when the request is over.

The simplest way is to put the object as a pnote:

sub getInstance {
  my $r=shift;

  return $r->pnotes->{Logger} if exists $r->pnotes->{Logger};
  return $r->pnotes->{Logger}=Logger->new;
}

No global $this!

When the request pool is destroyed all pnotes are destroyed as well.

In theory that also binds the current interpreter to the pool. That 
means it makes sure that the interpreter stays the same at least as 
long as the request pool exists no matter what PerlInterpScope says. 
But there were bugs with that in the past. So perhaps you have to 
upgrade your modperl.

And finally an advice, don't use a threaded MPM with modperl in 
production! If you want to help with the code it would be appreciated. 
A good starting point is the threading branch at 
http://svn.apache.org/repos/asf/perl/modperl/branches/threading

Torsten

--
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net

Fwd: MPM-safe mp2 Singleton Pattern?

Posted by Steven Siebert <sm...@gmail.com>.
Hello,

I want to implement a singleton pattern on my logger module.  During
initial instantiation, the logger module is seeded with some
information (ie. transactionId) and creates some (ie. requestTime).
What I want is for the logger object to be instantiated (if needed)
and/or retrieved from the Logger::getInstance() method for each HTTP
request...basically I don't want to have to pass the object around but
instead return a the reference to the instance when I need it.

First, some info about my environment: mp2 on RHEL.  The prefork MPM
is in use but I explicitly turned off worker as the existing
application I will be working against is not thread safe.

What I am running into is that the new instance is created for each
process and is accessible throughout the request as intended.
Unfortunately, what I am also noticing is that when the process is
reused by Apache, the previous logger instance still exists and is
pulled back by reference and therefore have incorrect parameters
(since the transactionID and requestTime has changed).  I believe this
is by design because it obviously would give a decent performance
boost under situations where this is OK.  However, this is not one of
these times =).

I thought of two solutions, both of which don't seem a great answer.
First was to explicitly DESTROY the logger object when I was done with
the request (which would work, since I have a controller/router
managing the request).  however, if something goes wrong I can't be
sure the logger would be destroyed.  Second was to create a factory
method in addition to the traditional singleton static method to
explicitly create a new instance and overwrite the existing.  I think
this would work with my environment (only prefork MPM) but it smells
as if it wouldn't be thread safe - I imagine a spawned threat would
overwrite and corrupt multiple threads on a process.  I included
psudo-code of the second theory below so you can pretty much see what
I am doing.

Is there any way to have a MPM-safe (specifically thread-safe)
singleton pattern?

P.S.  For those of you who noticed, even though the app I'm eventually
going to integrate with is not thread safe, I am building a SOA
mid-tier that I wish to release open source and personally reuse, so I
want it to be thread safe. =)


Thanks,

Steve

psudo code:

package Logger;

my $this; # singleton instance

sub getInstance { my ( $self, $transId ) = @_;
 unless (defined $this) {
    $self->createNewInstance($transId);
 }
 return $this;
}

sub createNewInstance { my ( $self, $transId ) = @_;
 my $vars = {'transId' => $transId};
 $this = bless $vars, $self;

 $this->_getRequestDate();

 return $this;
}
1;