A fix is available
APAR status
Closed as program error.
Error description
Applications that perform concurrent dynamic_cast in a multi-threaded environment may receive an incorrect return value from the dynamic_cast function. Below is a test program that demonstrates dynamic_cast returning an incorrect pointer value. #define CAST_SUCCESSFUL_OUTPUT 0 #define NUM_THREADS 60 #define FORCE_BAD_CAST 0 class A { public: // Since RTTI is included in the virtual method table there should be at least one virtual function. virtual ~A() { }; virtual void methodSpecificToInstance() = 0 ; }; class B : public A { public: void methodSpecificToInstance() { std::cout << "Method specific for B was invoked" << std::endl; }; ~B() { }; }; class C : public A { public: void methodSpecificToInstance() { std::cout << "Method specific for C was invoked" << std::endl; }; ~C() { }; }; class D : public A { public: void methodSpecificToInstance() { std::cout << "Method specific for D was invoked" << std::endl; }; ~D() { }; }; class E : public A { public: void methodSpecificToInstance() { std::cout << "Method specific for E was invoked" << std::endl; }; ~E() { }; }; class F : public A { public: void methodSpecificToInstance() { std::cout << "Method specific for F was invoked" << std::endl; }; ~F() { }; }; typedef std::vector<A*> ObjectVector; bool iKeepRunning = true; int threadNumber = 0; void* runCasts(void* = 0) { int thdNum = threadNumber; threadNumber++; int count = 0; ObjectVector myObjects; myObjects.resize(6); myObjects[0] = NULL; myObjects[1] = new B(); myObjects[2] = new C(); myObjects[3] = new D(); myObjects[4] = new E(); myObjects[5] = new F(); typedef std::tr1::mt19937 Engine_19937; Engine_19937 engine; engine.seed(time(NULL)); std::tr1::uniform_int<int> distribution(1,5); Engine_19937 engineSleep; engineSleep.seed(time(NULL)); std::tr1::uniform_int<int> distributionSleep(0,2); while (iKeepRunning && count != -1) { int index = distribution(engine); int sleepTime = distributionSleep(engineSleep); usleep(sleepTime*100); A* beforePtr = myObjects[index]; if (count %10000000 == 0) { std::cout << thdNum << ":" << sleepTime << ":" << count << ":" << index << std::endl; } if (index == 1) { if (FORCE_BAD_CAST) { if (count %10000003 == 1 ) { beforePtr = myObjects[3]; } } B* afterPtr = dynamic_cast<B*>(beforePtr); if (afterPtr == NULL) { std::cerr << "Cast failed - type A" << std::endl; } else if (beforePtr != afterPtr) { std::cerr << "Pointers differ after cast - type B" << std::endl; } else { if ( CAST_SUCCESSFUL_OUTPUT ) { std::cerr << "Successful cast - type B" << std::endl; } } } else if (index == 2) { C* afterPtr = dynamic_cast<C*>(beforePtr); if (afterPtr == NULL) { std::cerr << "Cast failed - type C" << std::endl; } else if (beforePtr != afterPtr) { std::cerr << "Pointers differ after cast - type C" << std::endl; } } else if (index == 3) { D* afterPtr = dynamic_cast<D*>(beforePtr); if (afterPtr == NULL) { std::cerr << "Cast failed - type D" << std::endl; } else if (beforePtr != afterPtr) { std::cerr << "Pointers differ after cast - type D" << std::endl; } } else if (index == 4) { E* afterPtr = dynamic_cast<E*>(beforePtr); if (afterPtr == NULL) { std::cerr << "Cast failed - type E" << std::endl; } else if (beforePtr != afterPtr) { std::cerr << "Pointers differ after cast - type E" << std::endl; } } else if (index == 5) { F* afterPtr = dynamic_cast<F*>(beforePtr); if (afterPtr == NULL) { std::cerr << "Cast failed - type F" << std::endl; } else if (beforePtr != afterPtr) { std::cerr << "Pointers differ after cast - type F" << std::endl; } } else { std::cerr << "Unknown index: " << index << std::endl; } count++; } } int main() { pthread_t thread_array[NUM_THREADS]; for (int i = 0 ; i < NUM_THREADS ; i++) { sleep(1); std::cout << "Starting thread " << i << std::endl; pthread_create(&thread_array[i], NULL, &runCasts, NULL); } runCasts(); sleep(10); iKeepRunning = false; } ===== ACTUAL OUTPUT: $./testProg Starting thread 0 0:2:0:4 . . Starting thread 59 59:2:0:5 60:2:0:5 Pointers differ after cast - type E ===== EXPECTED OUTPUT: There should be no "Pointers differ after cast" in the output.
Local fix
N/A
Problem summary
**************************************************************** * USERS AFFECTED: Multithreaded applications that run on z/OS * * V2R1 with LP64 and that use dynamic_cast * * function can be affected by this issue. * **************************************************************** * PROBLEM DESCRIPTION: There was a section in the C++ runtime * * (within dynamic_cast) where a lock for * * the return value of the dynamic_cast * * pointer was released and the * * dynamic_cast pointer was returned. But * * between the release of the lock and * * the return of the dynamic_cast * * pointer, there was a chance that * * another thread could change the return * * value of the dynamic_cast pointer. As * * a result, there was a small window for * * a race condition. * **************************************************************** * RECOMMENDATION: * ****************************************************************
Problem conclusion
Applied provided service.
Temporary fix
Comments
APAR Information
APAR number
PI15855
Reported component name
ANSI C++ CLASS
Reported component ID
568819807
Reported release
790
Status
CLOSED PER
PE
NoPE
HIPER
NoHIPER
Special Attention
NoSpecatt / Xsystem
Submitted date
2014-04-12
Closed date
2014-04-14
Last modified date
2014-05-02
APAR is sysrouted FROM one or more of the following:
APAR is sysrouted TO one or more of the following:
UI17014 LI78255
Modules/Macros
CELHDCTI CELQDCTI CEL4DCTI
Fix information
Fixed component name
ANSI C++ CLASS
Fixed component ID
568819807
Applicable component levels
R790 PSY UI17014
UP14/04/25 P F404
Fix is available
Select the PTF appropriate for your component level. You will be required to sign in. Distribution on physical media is not available in all countries.
[{"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SG19M","label":"APARs - z\/OS environment"},"Component":"","ARM Category":[],"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"790","Edition":"","Line of Business":{"code":"","label":""}},{"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SSTLTF","label":"z\/OS XL C\/C++"},"Component":"","ARM Category":[],"Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"790","Edition":"","Line of Business":{"code":"LOB08","label":"Cognitive Systems"}}]
Document Information
Modified date:
02 May 2014