The TclX wait command hangs after a fork if the following
conditions are met:
- TclX is loaded on tclsh8.4
- Tcl and TclX are compiled with --enable-threads.
- a fork is done but no execl is done and the
child exits
- the parent process issues a wait on the child pid
The bug can be easily reproduced with the following tcl
script:
package require Tclx 8.4
echo "using tcl $tcl_version + tclx [infox version]"
proc make_process {program {args {}}} {
echo "forking $program"
flush stdout; flush stderr
set pid [fork]
if {$pid == 0} {
catch {execl $program $args}
exit 1
} else {
return $pid
}
}
# cmdtrace on
set pid [make_process /bin/true]
puts -nonewline "waiting $pid ... "; flush stdout
puts [wait $pid]
set pid [make_process /some_bad_program]
puts -nonewline "waiting $pid ... "; flush stdout
puts [wait $pid]
The problem doesn't happen with Tcl8.3 or when Tcl and
TclX are
both compiled without thread support, as is the case of
ActiveTcl.
The problem seems to be in the exit of the child but
the visible
effect is that the wait in the parent hangs forever.
An strace of the processes (see attachment) shows that
when the
child process exits it sends a 'q' command to a thread
belonging to
the parent and then it probably waits a signal back
from the parent
to terminate. As the parent doesn't know how to handle
this message
the child hangs forever and the wait in the parent will
never return.
--
Massimo Dal Zotto <dz@debian.org>
strace log of the problem
Logged In: YES
user_id=189001
This seems really a Tcl8.4 bug. See also:
http://sourceforge.net/tracker/index.php?func=detail&aid=749639&group_id=10894&atid=110894
Logged In: YES
user_id=240
I get Tcl to crash with this simple bit of code:
package require Tclx
for {set i 0} {$i < 5} {incr i} {
set pid [fork]
if { $pid == 0 } {
break
} else {
puts $pid
}
}
tclsh8.4 [~/tmp]puts $tcl_patchLevel
8.4.2
Using the latest Tclx code.
Logged In: YES
user_id=240
Here is what happens with my code:
@ashland [~/tmp] $ ./forkthreadserver.tcl
30328
30329
30330
30331
Tcl_FinalizeNotifier: notifier pipe not initialized
Tcl_FinalizeNotifier: notifier pipe not initialized
Tcl_FinalizeNotifier: notifier pipe not initialized
30332
Tcl_FinalizeNotifier: notifier pipe not initialized
Aborted (core dumped)
Logged In: YES
user_id=72656
This is actually a core issue with handling of fork with
threads. The two are simply contradictory, and you have to
do all sorts of pthread magic to get them to behave. See
Tcl core bug 749639.
Logged In: YES
user_id=189001
Since most of tcl programs don't use threads would it be
possible to have
thread support compiled in but disabled by default and
enabled at runtime
with a command line switch? Something like:
$ tclsh non-threaded-app.tcl
$ tclsh -enable-threads threaded-app.tcl
Another possibility would be an enable_threads command which
would be
called automatically by the tcl thread library during
initialization.