Tcl Source Code

View Ticket
Login
Ticket UUID: 2918110
Title: Segfault from chan postevent
Type: Bug Version: obsolete: 8.6b1.1
Submitter: sbron Created on: 2009-12-20 14:09:55
Subsystem: 25. Channel System Assigned To: andreas_kupries
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2010-01-19 05:22:35
Resolution: Fixed Closed By: andreas_kupries
    Closed on: 2010-01-18 22:22:35
Description:
I'm trying to post a write event when a writable event handler is being installed on a reflected channel that is ready to be written to. At that point Tcl crashes with a segmentation fault. Chances are I'm not using the command correctly, but that should still not result in a segmentation fault.

The script to reproduce the problem is attached and this is the backtrace:

Program terminated with signal 11, Segmentation fault.
#0  0x00007ff4d325290e in TclEvalObjEx ()
   from /home/sbron/usr/lib/libtcl8.6.so 
#1  0x00007ff4d32b222f in TclChannelEventScriptInvoker ()                       
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#2  0x00007ff4d32b7811 in Tcl_NotifyChannel ()                                  
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#3  0x00007ff4d32bc716 in TclChanPostEventObjCmd ()                             
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#4  0x00007ff4d324c2c3 in TclNRRunCallbacks ()                                  
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#5  0x00007ff4d329bd37 in TclExecuteByteCode ()                                 
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#6  0x00007ff4d324c2c3 in TclNRRunCallbacks ()                                  
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#7  0x00007ff4d32bc947 in InvokeTclMethod ()                                    
   from /home/sbron/usr/lib/libtcl8.6.so                                        
#8  0x00007ff4d32bcbed in ReflectWatch ()
   from /home/sbron/usr/lib/libtcl8.6.so
#9  0x00007ff4d32b3e02 in Tcl_FileEventObjCmd ()
   from /home/sbron/usr/lib/libtcl8.6.so
#10 0x00007ff4d324c2c3 in TclNRRunCallbacks ()
   from /home/sbron/usr/lib/libtcl8.6.so
#11 0x00007ff4d3251d73 in TclEvalEx ()
   from /home/sbron/usr/lib/libtcl8.6.so
#12 0x00007ff4d3252146 in Tcl_EvalEx ()
   from /home/sbron/usr/lib/libtcl8.6.so
#13 0x00007ff4d32c37b1 in Tcl_FSEvalFileEx ()
   from /home/sbron/usr/lib/libtcl8.6.so
#14 0x00007ff4d32c9732 in Tcl_Main ()
   from /home/sbron/usr/lib/libtcl8.6.so
#15 0x0000000000400950 in main ()

OpenSuSE 11.2, x86_64
User Comments: andreas_kupries added on 2010-01-19 05:22:35:

allow_comments - 1

Fix committed to HEAD and Tcl 8.5 branch.

andreas_kupries added on 2010-01-19 04:58:34:
The diagnosis is basically ok ...

Tcl_CreateChannelHandler registers the new handler we want, this tells the IO system that we are willing to accept write events, this causes 'UpdateInterest' to be called, which calls the "watch" command of your reflected channel, which decides that we should send the event NOW, via 'postevent', which calls Tcl_NotifyChannel, and through that the designated callback, i.e. TclChannelEventScriptInvoker, which now operates on the allocated, but otherwise uninitialized EventScript structure. BOOM.

The C-level channels do not have this problem because none of them calls Tcl_NotifyChannel immediately in their watch proc, but only when an event is actually signed by the notifier (FileHandler callbacks).

For the reflected channel the problem is that the 'chan postevent' command has no reliable way of detecting that it is called directly from the 'watchProc' ... If we had that we could throw an error message telling the user that the postevent should be defered.

Without that your patch is in essence the way to go. Initialize everything in the structure before we create and register the channel handler with the IO core.

Regarding "without replicating so many commands", that is possible, but will require a boolean variable to remember if we have to call Tcl_CreateChannelHandler or not, i.e. something which holds the result of 'esPtr == NULL' even after we have allocated the structure and assigned to esPtr.

andreas_kupries added on 2010-01-19 04:16:59:

File Added - 359402: rtc-slides.pdf

andreas_kupries added on 2010-01-19 04:16:40:

File Added - 359401: rtc.pdf

andreas_kupries added on 2010-01-19 04:15:52:
Please note that Tcllib 1.12 contains examples on how to write reflected channels (and transformations). While these use TclOO as foundation, it should easy to cast these back to ensembles as well.

% teacup list tcl::chan ; teacup list tcl::trans
entity  name                  version platform
------- --------------------- ------- --------
package tcl::chan::core       1       tcl
package tcl::chan::events     1       tcl
package tcl::chan::fifo       1       tcl
package tcl::chan::fifo2      1       tcl
package tcl::chan::halfpipe   1       tcl
package tcl::chan::memchan    1       tcl
package tcl::chan::null       1       tcl
package tcl::chan::nullzero   1       tcl
package tcl::chan::random     1       tcl
package tcl::chan::string     1       tcl
package tcl::chan::textwindow 1       tcl
package tcl::chan::variable   1       tcl
package tcl::chan::zero       1       tcl
------- --------------------- ------- --------
13 entities found
entity  name                      version platform
------- ------------------------- ------- --------
package tcl::transform::adler32   1       tcl
package tcl::transform::base64    1       tcl
package tcl::transform::core      1       tcl
package tcl::transform::counter   1       tcl
package tcl::transform::crc32     1       tcl
package tcl::transform::hex       1       tcl
package tcl::transform::identity  1       tcl
package tcl::transform::limitsize 1       tcl
package tcl::transform::observe   1       tcl
package tcl::transform::otp       1       tcl
package tcl::transform::rot       1       tcl
package tcl::transform::spacer    1       tcl
package tcl::transform::zlib      1       tcl
------- ------------------------- ------- --------
13 entities found
andreask@gila:~/workbench/RefBugs>

Please also read the paper on Reflected Channels I am about to attach to this bug, which explains the innards, with emphasis on the event handling code.

Despite all this bing said, the core should of course not crash when called badly.

One part which my implementations always had is that the postevent is defered through a timer, which meant that the EventScriptRecord as always fully created and initialized.

sbron added on 2009-12-20 22:29:41:
The problem seems to be that the EventScriptRecord structure is not yet completely filled in before calling Tcl_CreateChannelHandler. The attached patch fixes that, although there may be a way to do this without replicating so many commands in both legs of the if.

sbron added on 2009-12-20 22:29:26:

File Added - 355889: 2918110.patch

sbron added on 2009-12-20 21:09:56:

File Added - 355882: rctest.tcl

Attachments: