Loading ...
Sorry, an error occurred while loading the content.

Re: [soaplite] SOAP::Lite interaction w/ Exception::Class results in Perl seg fault

Expand Messages
  • Paul Kulchenko
    Hi Peter, You re right. gen_id doesn t handle stringified objects well. There is another version that is protected from stringification (it s used in
    Message 1 of 4 , Jan 8, 2003
    • 0 Attachment
      Hi Peter,

      You're right. gen_id doesn't handle stringified objects well. There
      is another version that is protected from stringification (it's used
      in UDDI::Lite):

      sub gen_id { overload::StrVal($_[1]) =~ /\((0x\w+)\)/o; $1 }

      Performance is the reason why sprintf %U is used. The version that
      uses overload::StrVal is significantly slower and I hasn't been able
      to find a combination that performs well.

      It's easy to override gen_id in your version of serializer, but I'm
      not sure what's the best way to fix it once and for all. Thoughts?

      Best wishes, Paul.

      P.S. One related thought. I've been thinking about adding handling
      for Exception::Class (SOAP::Server::handle, 2221) or, perhaps,
      providing on_fault method on a server side, so that you can handle
      fault and return the result you need. It hasn't been implemented yet
      thought.

      --- "Peter Chen <petechen@...>"
      <petechen@...> wrote:
      > FYI - there seems to be a conflict/caveat using SOAP::Lite w/
      > Exception::Class that is severe enough to cause Perl to segfault.
      >
      > I encountered an odd case where a daemon using
      > SOAP::Transport::HTTP::Daemon some how caused perl (Mandrake 8.1,
      > Linux 2.4.16 kernel, perl-5.601-6mdk, SOAP::Lite 0.55,
      > Exception::Class 1.00) to segfault.
      >
      > Using the perl debugger, I was able to trace the problem to
      > gen_id()
      > at line 803 in SOAP/Lite.pm:
      >
      > sub gen_id { sprintf "%U", $_[1] }
      >
      > It seems that there is some black magic here, where the address of
      > a
      > reference is returned. And this function is not intended to handle
      > a
      > scalar.
      >
      > The problem is that when one of the dispatched functions uses
      > Exception::Class and throws such an exception. It dies with an
      > object, and not a scalar. This means when the SOAP fault is
      > serialized, gen_id() is called. However, the stringify operator is
      > overloaded for Exception::Class, so printing such an exception
      > object
      > will return $exception->message instead. This in turn causes
      > problems
      > with gen_id(), where sprintf("%U", $exception) becomes
      > sprintf("%U",
      > $exception->message).
      >
      > I circumvented the problem by catching the exception within the
      > function, then "die $exception->message" instead. However, this
      > seems
      > somewhat kludgey. Perhaps there is a cleaner fix in SOAP::Lite, so
      > it
      > can handle modules that use Exception::Class.
      >
      > Incidentally, a quick search in the archive shows that this is not
      > the
      > first time problems of this sort are reported. In last September,
      > there was a mention about Exception::Class as well.
      >
      > http://groups.yahoo.com/group/soaplite/message/1817
      >
      > Pete
      >
      >
      > ------------------------ Yahoo! Groups Sponsor
      >
      > To unsubscribe from this group, send an email to:
      > soaplite-unsubscribe@yahoogroups.com
      >
      >
      >
      > Your use of Yahoo! Groups is subject to
      > http://docs.yahoo.com/info/terms/
      >
      >


      __________________________________________________
      Do you Yahoo!?
      Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
      http://mailplus.yahoo.com
    • Peter Chen
      ... One possibility is a pragma like approach. For example, one can add a parameter in the import function, so one may: use SOAP::Lite gen_id = safe ;
      Message 2 of 4 , Jan 8, 2003
      • 0 Attachment
        On Wed, 2003-01-08 at 14:26, Paul Kulchenko wrote:
        > You're right. gen_id doesn't handle stringified objects well.
        ...
        > sub gen_id { overload::StrVal($_[1]) =~ /\((0x\w+)\)/o; $1 }
        >
        > Performance is the reason why sprintf %U is used. The version that
        > uses overload::StrVal is significantly slower and I hasn't been able
        > to find a combination that performs well.
        >
        > It's easy to override gen_id in your version of serializer, but I'm
        > not sure what's the best way to fix it once and for all. Thoughts?

        One possibility is a "pragma" like approach. For example, one can add a
        parameter in the import function, so one may:

        use SOAP::Lite 'gen_id' => 'safe';

        Different versions of gen_id() can be loaded based on its setting.

        I frequently see this for modules that have separate development and
        production mode. This is not a complete solution, but it gives people
        and option.

        > P.S. One related thought. I've been thinking about adding handling
        > for Exception::Class (SOAP::Server::handle, 2221) or, perhaps,
        > providing on_fault method on a server side, so that you can handle
        > fault and return the result you need. It hasn't been implemented yet
        > thought.

        I like this idea, even though I suspect this will take more work than my
        proposal above. Then again, they are not mutually exclusive. If there
        is such a callback, I may custom tailor how I serialize Exception::Class
        objects. For example, Exception::Class allows one to define custom
        fields, in on_fault method, I may then check the class of the exception
        object, and provide different serialization for different exception
        classes.

        Pete
      • dtikhonov
        Let s revisit this thread. I did my own investigation of the problem and realized that the problem is not stringification, but numeric conversion overloading
        Message 3 of 4 , Jan 25, 2006
        • 0 Attachment
          Let's revisit this thread. I did my own investigation of the problem
          and realized that the problem is not stringification, but numeric
          conversion overloading done in Error.pm. Here's my analysis from
          perlmonks.org[1]:

          ---------------------------------------------
          I have a server written in Perl that does some tasks that clients ask
          it to. Requests and responses are passed using soap, namely
          SOAP::Lite. Responses can be successful or unsuccessful. The latter
          are of two types: error codes plus honest-to-God exceptions (well, as
          close as Perl comes to them, anyway) of type Error or
          Exception::Class. The problem occurs when SOAP::Serializer tries to
          serialize objects of type Error. Error.pm has the following code
          (shortened for our purposes):

          use overload ("0+" => 'value');
          sub value {
          my $self = shift;
          exists $self->{'-value'} ? $self->{'-value'} : undef;
          }

          Note that this subroutine may return undef. Now, SOAP::Serializer
          calls subroutine gen_id on references, which for normal objects is
          just the value of memory address:

          sub gen_id { sprintf "%U", $_[1] }

          Now, the problem is that when objects of type Error do not have a
          value (returns undef), this produces a segfault in perl 5.6.1. This
          problem can be demonstrated with the following short script:

          package My;

          use overload ('0+' => 'num_conv');
          sub new {
          my $self = shift;
          bless {}, ref($self) || $self;
          }
          sub num_conv { undef }

          package main;
          my $var = My->new;
          print int($var);
          ---------------------------------------------

          We can see that gen_id should try to detect whether object has numeric
          conversion overloaded and if it does, use a different scheme to get
          the ID (such as Scalar::Util::refaddr, also suggested in the perlmonks
          thread).

          Thoughts?

          - Dmitri.

          1. http://www.perlmonks.org/?node_id=525293
        Your message has been successfully submitted and would be delivered to recipients shortly.