Tcl Source Code

View Ticket
Login
Ticket UUID: 960414
Title: exit causes segmentation violation with Oratcl extension
Type: Bug Version: obsolete: 8.5a2
Submitter: tmh Created on: 2004-05-25 21:13:47
Subsystem: 16. Commands A-H Assigned To: hobbs
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2005-02-17 08:52:26
Resolution: Duplicate Closed By: hobbs
    Closed on: 2005-02-17 01:52:26
Description:
Something has changed in the exit handling of Tcl since
the 8.4.6 release.  This change causes a segmentation
violation when using
the Oratcl extension.

This is similar to a previous Bug ID # 2560.  At issue
is that the Oracle library (that cannot be changed)
that is linked dynamically at runtime with Oratcl, has
atexit() calls embedded in the library.  These calls
fire when tcl finally calls exit().  If the Oratcl
extension library is unloaded before the exit()
happens, then the atexit() can no longer reference the
symbols in the Oratcl library that called the oracle
library.

I am listing this as a Tcl Bug because, Oratcl has not
been changed.
This works just fine in Tcl 8.4.6.

jumpgate: [75] > gdb /opt/tcl8.5a2d/bin/tclsh8.5 
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it
under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show
warranty" for details.
This GDB was configured as "sparc-sun-solaris2.7"...
(gdb) run
Starting program: /opt/tcl8.5a2d/bin/tclsh8.5 
% package require Oratcl
4.2
% set lda [oralogon t/b@c]
oralogon: invalid username/password; logon denied
% exit

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0xfe842e54.

Maybe there is a way to preserve the library so that it
is not unloaded, but I cannot tell from the
documentation how to do that.

Also,  Oratcl does use an exit handler.  If I add an
exit(0) to my exit handler, the core dump goes away,
but none of the other things in Tcl_Finalize occur.
User Comments: hobbs added on 2005-02-17 08:52:25:
Logged In: YES 
user_id=72656

dup as 1011715

tmh added on 2005-02-17 02:04:14:
Logged In: YES 
user_id=92123

New version of Oratcl does not suffer from this behavior so I 
am canceling the bug report.

tmh added on 2004-06-01 00:38:44:
Logged In: YES 
user_id=92123

Ok I agree that package require is the wrong place to tweak.

I am wondering if this is not related to TIP 100.
I do not have a Oratcl_Unload proc defined, so I do not know
why the oratcl library is being unloaded.

Do you have any comments on the patch to tclLoadDl.c that 
I have uploaded.  I really would like to figure this out before 
Tcl 8.5 is released stable as this will be a nightmare to 
support.

Thanks
Todd

dgp added on 2004-06-01 00:30:18:
Logged In: YES 
user_id=80530

[package require] is the
wrong place to add tweaks
to the operation of
[load] and [unload].

tmh added on 2004-05-30 22:56:02:

File Added - 88949: diff

Logged In: YES 
user_id=92123

I have found a solution but the impact on others, I cannot 
address...  It would be nice if there was an API to turn on/off 
thischange for particular packages .

Something like 

package require -preserve Oratcl

tmh added on 2004-05-30 21:42:19:
Logged In: YES 
user_id=92123

I have found some additional information from oracle..

---------------

symptom: Dynamically unloading shared library fails 
symptom: SIGSEGV 11* segmentation violation 
symptom: Core dump is generated 

cause: A program, either Pro*C or OCI, that dynamically 
loads and unloads a shared library that includes libclntsh.so 
will cause a core dump on exit after dynamically unloading the 
shared library. This will only occur if a connect and 
disconnect to Oracle is performed. 

This documented in <bug:2012268>:CORE DUMP ON EXIT OF 
PRO*C PROGRAM USING DLCLOSE(). The dlopen loads the 
users shared object, and this in turn causes libclntsh.so to be 
loaded into the program. The Oracle trace code in the client 
registers an exit handler by calling "atexit()". This registers a 
function which resides inside libclntsh.so to be called at exit 
from the process. dlclose() unloads the users library and 
libclntsh.so. exit() tries to call "epc_exit_handler" which is 
now unmapped. 

-------

Since Tcl 8.5 now calls dlclose for packages where 8.4  
apparently does not.  Would it be too late for a feature that 
allows package writers the option to skip the dlclose ?

Also, Oracle provides a solution (hack) to get around the core 
dump.  This is apparently a Solaris only issue.

Workaround (Solaris specific): 

Before starting the process which performs dlopen/dlclose of 
a module linked with Oracle set the environment variable 
LD_PRELOAD to point to the libclntsh.so file that is being 
used. For example: 

setenv LD_PRELOAD 
$ORACLE_HOME/rdbms/lib/libclntsh.so.8.0 

This maps libclntsh permanently and avoids the core dump. 
This variable must only be set for programs that encounter 
the core dump and not set generally. 


Since this is clearly Oracle's fault, Would someone kindly 
change the close the status of this bug report.

Thanks
Todd

tmh added on 2004-05-26 11:01:44:
Logged In: YES 
user_id=92123

I have attached a file showing my gdb session and the results.

tmh added on 2004-05-26 10:50:29:

File Added - 88445: typescript

mistachkin added on 2004-05-26 08:06:00:
Logged In: YES 
user_id=113501

What line in the Tcl core actually causes the segfault 
(especially, is it inside of Tcl_Finalize)?

Is your exit handler actually being called (when it's not 
commented out, that is)?

Do you have a stack trace?

tmh added on 2004-05-26 04:55:22:
Logged In: YES 
user_id=92123

in the init area.
                Tcl_CreateExitHandler ((Tcl_ExitProc *)
Oratcl_Exit,
                                       (ClientData)
OratclStatePtr);



void
Oratcl_Exit (clientData)
        ClientData clientData;
{
        Oratcl_Clean(clientData);

        Tcl_DecrRefCount(OMV_null);
        Tcl_DecrRefCount(OMV_zero);
}

        /* callback - clean up procs left open on
interpreter deletetion */
        Tcl_CallWhenDeleted(interp,
                            (Tcl_InterpDeleteProc *)
Oratcl_Delete,
                            (ClientData) OratclStatePtr);




More to the point.

If I comment out all exit handling from the Oratcl code. 
(It's just memory
leaks after all :) I still get the seg fault on exit.

Todd
Also there is a interp delete callback for slave interps.

mistachkin added on 2004-05-26 04:38:48:
Logged In: YES 
user_id=113501

Are you simply exiting tclsh or is your application calling one 
of the Tcl C API functions, if so, which one?

As long as Tcl_SetExitProc is never called with a non-NULL 
pointer, the new exit handling from TIP #121 should not have 
any effect.  

Is Tcl_Finalize actually being called?  If it is, then Tcl is using 
the default exit handling and the bug may be in Tcl_Finalize 
itself.

Attachments: