IBM Support

IZ70953: APP SEGFAULT IN CLEANUPV6()

Subscribe

You can track all active APARs for this component.

 

APAR status

  • Closed as program error.

Error description

  • A large application segfaults during runtime and emits the
    following traceback showing that the fault was trapped in the
    C++ runtime call cleanupv6()
    
    Segmentation fault in
    cleanupv6.printActiveExceptions__FP9Exception at
    0x9000000058569b8 ($t1)
    0x9000000058569b8 (printActiveExceptions__FP9Exception+0x78)
    e8840010          ld   r4,0x10(r4)
    (dbx) where
    cleanupv6.printActiveExceptions__FP9Exception(??) at
    0x9000000058569b8
    __CleanupCatchV6a(??) at 0x900000005856bb0
    setDominator__19SzkAlgSemanticGraphFUiT1(??, ??, ??) at
    0x101a77c68
    BitSetLoop__H17UpdateRootEntries_RC9szkBitSet17UpdateRootEntries
    _Uc(0x200014000005b4c, 0x70000004989f030, 0x1100000001) at
    0x101a3b668
    addGraphChildren__19SzkAlgSemanticGraphFPC7AB_DATAPC4TABH(??,
    ??, ??) at 0x101a387d4
    ab_mi_bind_mi_nodes__FP20ab_kmeth_syinf_struc(??) at 0x101a4c970
    
    ...
    
    
    A reduced test case:
    
    
    ********************* start of test.cpp *********************
    #include <stdio.h>
    
    class DummyError
    {
    public:
      DummyError() {};
      // empty dtor caused missing cleanup call
      ~DummyError() {};
    };
    
    void getIndexOfNodeEntry()
    {
      throw DummyError();
    }
    
    void addNodeEntry()
    {
      try
      {
      getIndexOfNodeEntry();
      }
      catch(...)
      {
      printf("addNodeEntry caught exception\n");
      }
    }
    
    void getNodeEntry()
    {
      getIndexOfNodeEntry();
    }
    
    int getNodeEntry2()
    {
      printf("the second getNodeEntry\n");
      return 5;
    }
    
    void addNewStrRefCnt1Children()
    {
      addNodeEntry();
    }
    
    int addStringHandler()
    {
      try
      {
      getNodeEntry();
      return 1;
      }
      catch(DummyError)
      {
      printf("addStringHandler caught exception #1\n");
      addNewStrRefCnt1Children();
      printf("addStringHandler caught exception #2\n");
      // seg fault caused by missing cleanup call before return
    statement
      return getNodeEntry2();
      }
    }
    void setDominator()
    {
      try
      {
      getNodeEntry();
      }
      catch(...)
      {
      printf("setDominator caught exception #1\n");
      addNodeEntry();
      printf("setDominator caught exception #2\n");
      addStringHandler();
      printf("setDominator caught exception #3\n");
      }
    }
    
    int main()
    {
      setDominator();
      return 55;
    }
    ********************* end of test.cpp *********************
    
    Compile and run test.cpp:
    
    Segmentation fault (core dumped)
    

Local fix

  • Make the below empty destructor non-empty.
      ~DummyError() {};
    

Problem summary

  • USER AFFECTED:
    Program with a catch block that meets the following conditions:
    1. Has a return statement
    2. The exception class caught has an empty destructor (dtor)
    
    PROBLEM DESCRIPTION:
    Program segfaults at runtime during the exception cleanup
    function.
    The exception cleanup function is usually exectued at the end
    of each catch block.
    When a return statement is present in the catch block, an extra
    cleanup call needs
    to be inserted before the return statement in order to ensure
    the cleanup function
    is called before returning.  In this case, the cleanup call is
    not inserted, leading
    to the seg fult (due to the skipped cleanup call, the next
    cleanup call is exectued
    with a mismatched exception pointer).
    

Problem conclusion

  • The frontend first checks if the exception class has a user
    defined destructor,
    if not, then a cleanup call will be inserted. When the
    exception class has a user
    defined destructor, the cleanup call is associated with the
    destructor state change instead.
    However, as an optimization, when the destructor is either
    empty or trivial, there will be no
    destructor state change associated with it.  As a result, when
    an exception class has an empty
    destructor, the cleanup call will fail to be inserted.  To fix
    this problem, the
    initial check is extended to verify if the exception class's
    destructor is empty or trivial,
    if so, then insert the cleanup call right away (since there
    will be no destructor state change
    associated with it).
    

Temporary fix

Comments

APAR Information

  • APAR number

    IZ70953

  • Reported component name

    XL C++ AIX

  • Reported component ID

    5724U8100

  • Reported release

    A10

  • Status

    CLOSED PER

  • PE

    NoPE

  • HIPER

    NoHIPER

  • Special Attention

    NoSpecatt

  • Submitted date

    2010-02-24

  • Closed date

    2010-02-24

  • Last modified date

    2010-02-24

  • APAR is sysrouted FROM one or more of the following:

    IZ66785

  • APAR is sysrouted TO one or more of the following:

Fix information

  • Fixed component name

    XL C++ AIX

  • Fixed component ID

    5724U8100

Applicable component levels

[{"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SSJT9L","label":"XL C\/C++"},"Component":"","ARM Category":[],"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"A.1","Edition":"","Line of Business":{"code":"LOB08","label":"Cognitive Systems"}}]

Document Information

Modified date:
24 February 2010