vrogier / ocilib

OCILIB (C and C++ Drivers for Oracle) - Open source C and C++ library for accessing Oracle databases
http://www.ocilib.net
Apache License 2.0
321 stars 117 forks source link

Subscription.Register crashes if subscribtion files #3

Closed kornefalk closed 9 years ago

kornefalk commented 9 years ago

Running example code from "Database notifications" will cause crash if Register fails

  Subscription sub;
  sub.Register(con, "sub-00", Subscription::AllChanges, EventHandler, 5468, 0);

Tested both running on Red Hat Enterprise Linux Server release 6.5 (Santiago) and Oracle Solaris 10 8/11 s10s_u10wos_17b SPARC using GCC 4.9.2 compiler.

Running sample code ``` c++ Step 1 Step 2 Step 3 Step 4 Step 5 Step 6 Step 7 Step 8 *** glibc detected *** ./eventTest: double free or corruption (!prev): 0x000000000191d030 *** ======= Backtrace: ========= /lib64/libc.so.6[0x3edb475e66] /lib64/libc.so.6[0x3edb4789b3] /vobs/thirdparty/ocilib/installed/linux/lib/libocilib.so.4(OCI_StatementFree+0x4e)[0x7f087aab85ae] ./eventTest[0x409641] ./eventTest[0x409868] ./eventTest[0x40c1ce] /lib64/libc.so.6(__libc_start_main+0xfd)[0x3edb41ed5d] ./eventTest[0x404211] ```

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production With the Partitioning, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options

Running with gdb ``` c++ Program received signal SIGABRT, Aborted. 0x0000003edb432625 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 64 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (gdb) bt #0 0x0000003edb432625 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 #1 0x0000003edb433e05 in abort () at abort.c:92 #2 0x0000003edb470537 in __libc_message (do_abort=2, fmt=0x3edb558820 " glibc detected %s: %s: 0x%s **\n") at ../sysdeps/unix/sysv/linux/libc_fatal.c:198 #3 0x0000003edb475e66 in malloc_printerr (action=3, str=0x3edb558bb0 "double free or corruption (!prev)", ptr=) at malloc.c:6336 #4 0x0000003edb4789b3 in _int_free (av=0x3edb78fe80, p=0x6fd030, have_lock=0) at malloc.c:4832 #5 0x00007ffff7dd85ae in OCI_StatementFree () from /vobs/thirdparty/ocilib/installed/linux/lib/libocilib.so.4 #6 0x0000000000409641 in ocilib::HandleHolder::SmartHandle::~SmartHandle() () at /home/kornefab/ocilib/linux/include/ocilib_impl.hpp:702 #7 0x0000000000409868 in ocilib::HandleHolder::SmartHandle::Release(ocilib::HandleHolder) () at /home/kornefab/ocilib/linux/include/ocilib_impl.hpp:710 #8 0x000000000040c1ce in main () at eventTest.cpp:38 ```

source code ``` c++ #include #include "ocilib.hpp" #include using namespace ocilib; using namespace std; #ifdef _WINDOWS #define sleep(x) Sleep(x*1000) #endif #define WaitForEvents() sleep(5) #define WaitForDatabase() sleep(60) static std::map EventTypes; static std::map ObjectEvents; void EventHandler(Event &evt); void SetupNames(); int main(int argc, char* argv[]) { if (argc != 4) // Check number of arguments { cout << "eventTest user pwd connection" << endl; return -1; } string user(argv[1]); string pwd(argv[2]); string connect(argv[3]); int count=0; SetupNames(); cerr << "Step " << (++count) << endl; try { Environment::Initialize(Environment::Events); cerr << "Step " << (++count) << endl; //Connection con("db", "usr", "pwd"); Connection con(connect, user, pwd); cerr << "Step " << (++count) << endl; con.SetAutoCommit(true); cerr << "Step " << (++count) << endl; Statement st(con); cerr << "Step " << (++count) << endl; st.Execute("create table table1(code number)"); cerr << "Step " << (++count) << endl; st.Execute("create table table2(str varchar2(10))"); cerr << "Step " << (++count) << endl; Subscription sub; cerr << "Step " << (++count) << endl; sub.Register(con, "sub-00", Subscription::AllChanges, EventHandler, 5468, 0); cerr << "Step " << (++count) << endl; sub.Watch("select * from table1"); cerr << "Step " << (++count) << endl; sub.Watch("select * from table2"); cerr << "Step " << (++count) << endl; st.Execute("alter table table1 add price number"); cerr << "Step " << (++count) << endl; WaitForEvents(); cerr << "Step " << (++count) << endl; st.Execute("insert into table1 values(1, 10.5)"); cerr << "Step " << (++count) << endl; st.Execute("insert into table2 values('shoes')"); cerr << "Step " << (++count) << endl; WaitForEvents(); cerr << "Step " << (++count) << endl; st.Execute("update table1 set price = 13.5 where code = 1"); cerr << "Step " << (++count) << endl; st.Execute("delete from table2 "); cerr << "Step " << (++count) << endl; WaitForEvents(); cerr << "Step " << (++count) << endl; st.Execute("drop table table1"); cerr << "Step " << (++count) << endl; st.Execute("drop table table2"); cerr << "Step " << (++count) << endl; WaitForEvents(); cerr << "Step " << (++count) << endl; con.Close(); cerr << "Step " << (++count) << endl; /* start remote instance */ cerr << "Step " << (++count) << endl; Environment::StartDatabase("db", "sys_usr", "sys_pwd", Environment::StartForce, Environment::StartFull); cerr << "Step " << (++count) << endl; /* shutdown remote instance */ Environment::ShutdownDatabase("db", "sys_usr", "sys_pwd", Environment::ShutdownAbort, Environment::ShutdownFull); cerr << "Step " << (++count) << endl; WaitForDatabase(); cerr << "Step " << (++count) << endl; sub.Unregister(); cerr << "Step " << (++count) << endl; } catch (std::exception &ex) { std::cout << ex.what() << std::endl; } Environment::Cleanup(); } void SetupNames() { EventTypes[Event::DatabaseStart] = "Startup"; EventTypes[Event::DatabaseShutdown] = "Shutdown"; EventTypes[Event::DatabaseShutdownAny] = "Shutdown Any"; EventTypes[Event::DatabaseDrop] = "Drop Database"; EventTypes[Event::Unregister] = "Unregister"; EventTypes[Event::ObjectChanged] = "Object Changed"; ObjectEvents[Event::ObjectInserted] = "Insert"; ObjectEvents[Event::ObjectUpdated] = "Update"; ObjectEvents[Event::ObjectDeleted] = "Delete"; ObjectEvents[Event::ObjectAltered] = "Alter"; ObjectEvents[Event::ObjectDropped] = "Drop"; ObjectEvents[Event::ObjectGeneric] = "Generic"; } void EventHandler(Event &evt) { static int count=0; cerr << "EventHandler " << (++count) << endl; std::cout << "** Notification : " << evt.GetSubscription().GetName() << std::endl; std::cout << "** Database : " << evt.GetDatabaseName() << std::endl; std::cout << "** Event : " << EventTypes[evt.GetType()] << std::endl; if (evt.GetType() == Event::ObjectChanged) { std::cout << ".... Object : " << evt.GetObjectName() << std::endl; std::cout << ".... Action : " << ObjectEvents[evt.GetObjectEvent()] << std::endl; std::cout << ".... RowID : " << evt.GetRowID() << std::endl; } std::cout << std::endl; } ```

vrogier commented 9 years ago

Hi,

I've found the root cause and committed a fix for it :) Let me know if the issue is solved on your side with latest code (C and C++ code) in order to close the issue.

Thanks

Regards,

Vincent

kornefalk commented 9 years ago

Corrections verified successfully.

Now I get the Oracle desired error (ORA-29970: Specified registration id does not exist).

vrogier commented 9 years ago

good :)