Hello,
some years ago, we have developed a C library API (.so or .dll) used to access one of our product databases in a customer environment using Oracle. To access the database from our library, we use the Oracle Call Interface.
The original version has been developed against Oracle 9 and has been running for years in Solaris/Sparc and Windows/x86 environment.
Now one of the Solaris/Sparc customers is migrating to Oracle 12c. So we recompiled the library against Oracle 12c Instant Client for Solaris/Sparc.
The same application now gets a segmentation fault on the second invocation of OCIEnvCreate when running with Oracle 12c.
Isolating the problem, we found the following sequence of OCI related calls:
OCIEnvCreate(..,OCI_THREADED,0,0,0,0,0,0);
OCIHandleAlloc(...)
OCILogon(..)
... several successfull database calls
OCILogoff();
OCIFreeHandle()
OCITerminate
This sequence is working perfectly when executed the first time. If the same sequence is executed again in the same process, the OCIEnvCreate crashes with a segmentation fault (for Oracle 12c) but runs perfectly with Oracle 9i. When trying to do the same in a Windows environment (against Oracle 11g), the second call to OCIEnvCreate also crashes, with a totally corrupted call stack.
The Oracle documentation says that an OCITerminate should be executed only once per process and is the counterpart of OCIInitialize (which is part of the OCIEnvCreate execution). So elementary logic says that an OCIEnvCreate also should be executed only once. But in the documentation of OCIEnvCreate I find: "There can be multiple environments in OCI, each with its own environment modes." and "If you are writing a DLL or a shared library using OCI library then this call should definitely be used instead of OCIInitialize()
and OCIEnvInit()
call."
So my question is: Is it allowed to call OCIEnvCreate again after a call to OCITerminate and if so - how is this done correctly?
Wolfgang Rupprath