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

SOAP::Lite interaction w/ Exception::Class results in Perl seg fault

Expand Messages
  • Peter Chen <petechen@dragon.rutgers.edu>
    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
    Message 1 of 4 , Jan 8, 2003
    • 0 Attachment
      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
    • 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 2 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 3 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 4 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.