> > - all ports are closed, but what about other open files that are not > > ports ? My application opens many files in C that are not known to > > guile. Shouldn't these be closed as well ? > > > From this, I gather you have a C application that has Guile embedded, > right?
Yes. > (...) it could > be a workable solution (since you control all the C code) to just open > all files with the FD_CLOEXEC flag set, assuming you don't want to share > these file descriptors with the child. In the latter case, you are (in > general) a bit out of luck; perhaps this[0] LWN discussion can shed some > light on the general issue here. Very interresting reading, but: - If there is no better way then guile doc should definitively state this - Why not use the "good old way" of execing, ie fork then close everything but stdin/out/err, then exec. I don't have R.Stevens book at hand, but see [0] for an example [0] http://www.enderunix.org/docs/eng/daemon.php > > - what if when forking some other guile thread hold one of the internal > > lock (for instance, the lock protecting the port table) ? Then the > > code between the fork and the exec (which loop on all ports, amongst > > other things) may try to grab this internal mutex, deadlocking. > > > I've not yet done multithreading with Guile, but I think you are right; > Guile should use pthread_atfork() as explained at[1], but it apparently > does not (or at least so "git grep" indicated). This sounds like a bug; > could you come up with an example program that has a good chance to run > into this suspected issue? I attached 2 files: - "guile deadlock.scm > /tmp/log" deadlocks after around 12k lines of output for me - more surprisingly, "guile crash.scm > /dev/log" segfaults with this backtrace : Thread 2 (Thread 30144): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00007fccbe1d30e9 in _L_lock_953 () from /lib/libpthread.so.0 #2 0x00007fccbe1d2f0b in __pthread_mutex_lock (mutex=0x7fccbf01ec60) at pthread_mutex_lock.c:61 #3 0x00007fccbedd017c in scm_pthread_mutex_lock (mutex=0x7fccbf01ec60) at threads.c:1482 #4 0x00007fccbed70c61 in scm_gc_for_newcell (freelist=0x7fccbf0262a0, free_cells=0xb2c0b8) at gc.c:484 #5 0x00007fccbed86201 in scm_cell (car=140517355806736, cdr=140517355823216) at ../libguile/inline.h:122 #6 0x00007fccbed44b63 in scm_acons (key=0x7fccbf142100, value=0x7fccbf13e020, alist=0x7fccbf142070) at alist.c:43 #7 0x00007fccbed5fbed in ceval (x=0x7fccbf142010, env=0x7fccbf13e070) at eval.c:4300 #8 0x00007fccbed63b15 in scm_i_eval_x (exp=0x7fccbf148750, env=0x7fccbf1486e0) at eval.c:5900 #9 0x00007fccbed63c8c in scm_primitive_eval_x (exp=0x7fccbf148750) at eval.c:5921 #10 0x00007fccbed890f6 in scm_primitive_load (filename=0x7fccbf1e2c60) at load.c:109 #11 0x00007fccbed5f7a5 in ceval (x=0x404, env=0x7fccbf182b30) at eval.c:4232 #12 0x00007fccbed63c28 in scm_i_eval (exp=0x7fccbf182b90, env=0x7fccbf182b30) at eval.c:5910 #13 0x00007fccbed4b088 in scm_start_stack (id=0x7fccbf1cc2c0, exp=0x7fccbf206270, env=0x7fccbf182b30) at debug.c:457 #14 0x00007fccbed4b14a in scm_m_start_stack (exp=0x7fccbf206280, env=0x7fccbf182b30) at debug.c:473 #15 0x00007fccbed611b9 in scm_apply (proc=0x7fccbf2156a0, arg1=0x7fccbf2062e0, args=0x7fccbf182b30) at eval.c:4882 #16 0x00007fccbed5efcc in ceval (x=0x7fccbf2062e0, env=0x7fccbf182b30) at eval.c:4059 #17 0x00007fccbed61adb in scm_apply (proc=0x7fccbf182aa0, arg1=0x404, args=0x7fccbf182b30) at eval.c:5012 #18 0x00007fccbed60cf7 in scm_call_0 (proc=0x7fccbf182ac0) at eval.c:4666 #19 0x00007fccbed6e04c in apply_thunk (thunk=0x7fccbf182ac0) at fluids.c:400 #20 0x00007fccbed6e250 in scm_c_with_fluid (fluid=0x7fccbf1c1e20, value=0x4, cproc=0x7fccbed6e034 <apply_thunk>, cdata=0x7fccbf182ac0) at fluids.c:463 #21 0x00007fccbed6e202 in scm_with_fluid (fluid=0x7fccbf1c1e20, value=0x4, thunk=0x7fccbf182ac0) at fluids.c:450 #22 0x00007fccbed60589 in ceval (x=0x7fccbf206230, env=0x7fccbf182a40) at eval.c:4547 #23 0x00007fccbed61adb in scm_apply (proc=0x7fccbf182630, arg1=0x404, args=0x7fccbf1828d0) at eval.c:5012 #24 0x00007fccbed60cf7 in scm_call_0 (proc=0x7fccbf182650) at eval.c:4666 #25 0x00007fccbed4e980 in scm_dynamic_wind (in_guard=0x7fccbf1827e0, thunk=0x7fccbf182650, out_guard=0x7fccbf182820) at dynwind.c:111 #26 0x00007fccbed60589 in ceval (x=0x7fccbf1abdc0, env=0x7fccbf182770) at eval.c:4547 #27 0x00007fccbed5b46c in ceval (x=0x7fccbf1821b0, env=0x7fccbf1825a0) at eval.c:3368 #28 0x00007fccbed63b15 in scm_i_eval_x (exp=0x7fccbf182540, env=0x7fccbf1825a0) at eval.c:5900 #29 0x00007fccbed63c8c in scm_primitive_eval_x (exp=0x7fccbf182540) at eval.c:5921 #30 0x00007fccbed63d37 in scm_eval_x (exp=0x7fccbf182540, module_or_state=0x7fccbf1e3120) at eval.c:5956 #31 0x00007fccbedacd1e in scm_shell (argc=2, argv=0x7fff6d32e308) at script.c:737 #32 0x00000000004006b8 in inner_main (closure=0x0, argc=2, argv=0x7fff6d32e308) at guile.c:53 #33 0x00007fccbed85eba in invoke_main_func (body_data=0x7fff6d32e1c0) at init.c:367 #34 0x00007fccbed497f6 in c_body (d=0x7fff6d32e100) at continuations.c:349 #35 0x00007fccbedd0e1f in scm_c_catch (tag=0x104, body=0x7fccbed497ce <c_body>, body_data=0x7fff6d32e100, handler=0x7fccbed49805 <c_handler>, handler_data=0x7fff6d32e100, pre_unwind_handler=0x7fccbedd1763 <scm_handle_by_message_noexit>, pre_unwind_handler_data=0x0) at throw.c:203 #36 0x00007fccbed49792 in scm_i_with_continuation_barrier (body=0x7fccbed497ce <c_body>, body_data=0x7fff6d32e100, handler=0x7fccbed49805 <c_handler>, handler_data=0x7fff6d32e100, pre_unwind_handler=0x7fccbedd1763 <scm_handle_by_message_noexit>, pre_unwind_handler_data=0x0) at continuations.c:325 #37 0x00007fccbed49881 in scm_c_with_continuation_barrier (func=0x7fccbed85e62 <invoke_main_func>, data=0x7fff6d32e1c0) at continuations.c:367 #38 0x00007fccbedced99 in scm_i_with_guile_and_parent (func=0x7fccbed85e62 <invoke_main_func>, data=0x7fff6d32e1c0, parent=0x0) at threads.c:733 #39 0x00007fccbedced5a in scm_with_guile (func=0x7fccbed85e62 <invoke_main_func>, data=0x7fff6d32e1c0) at threads.c:721 #40 0x00007fccbed85e43 in scm_boot_guile (argc=2, argv=0x7fff6d32e308, main_func=0x400694 <inner_main>, closure=0x0) at init.c:350 #41 0x00000000004006e5 in main (argc=2, argv=0x7fff6d32e308) at guile.c:63 Thread 1 (Thread 30145): #0 0x00007fccbed72f69 in scm_i_sweep_some_segments (fl=0x7fccbf0262a0) at gc-segment.c:350 #1 0x00007fccbed70c87 in scm_gc_for_newcell (freelist=0x7fccbf0262a0, free_cells=0xb45498) at gc.c:487 #2 0x00007fccbed86201 in scm_cell (car=140517355786256, cdr=140517355823216) at ../libguile/inline.h:122 #3 0x00007fccbed44b63 in scm_acons (key=0x7fccbf142100, value=0x7fccbf139020, alist=0x7fccbf142070) at alist.c:43 #4 0x00007fccbed5fbed in ceval (x=0x7fccbf142010, env=0x7fccbf139070) at eval.c:4300 #5 0x00007fccbed61adb in scm_apply (proc=0x7fccbf148780, arg1=0x404, args=0x7fccbf14bc60) at eval.c:5012 #6 0x00007fccbed60cf7 in scm_call_0 (proc=0x7fccbf148760) at eval.c:4666 #7 0x00007fccbedd13bf in scm_body_thunk (body_data=0x7fccbdc63b50) at throw.c:355 #8 0x00007fccbedd0e1f in scm_c_catch (tag=0x104, body=0x7fccbedd139b <scm_body_thunk>, body_data=0x7fccbdc63b50, handler=0x7fccbedd13c1 <scm_handle_by_proc>, handler_data=0x7fccbdc63b38, pre_unwind_handler=0, pre_unwind_handler_data=0x7fccbdc63b30) at throw.c:203 #9 0x00007fccbedd18e4 in scm_catch_with_pre_unwind_handler (key=0x104, thunk=0x7fccbf148760, handler=0x7fccbf13ae50, pre_unwind_handler=0x204) at throw.c:587 #10 0x00007fccbedd191c in scm_catch (key=0x104, thunk=0x7fccbf148760, handler=0x7fccbf13ae50) at throw.c:601 #11 0x00007fccbedceea6 in really_launch (d=0x7fff6d32ca30) at threads.c:778 #12 0x00007fccbed497f6 in c_body (d=0x7fccbdc63e40) at continuations.c:349 #13 0x00007fccbedd0e1f in scm_c_catch (tag=0x104, body=0x7fccbed497ce <c_body>, body_data=0x7fccbdc63e40, handler=0x7fccbed49805 <c_handler>, handler_data=0x7fccbdc63e40, pre_unwind_handler=0x7fccbedd1763 <scm_handle_by_message_noexit>, pre_unwind_handler_data=0x0) at throw.c:203 #14 0x00007fccbed49792 in scm_i_with_continuation_barrier (body=0x7fccbed497ce <c_body>, body_data=0x7fccbdc63e40, handler=0x7fccbed49805 <c_handler>, handler_data=0x7fccbdc63e40, pre_unwind_handler=0x7fccbedd1763 <scm_handle_by_message_noexit>, pre_unwind_handler_data=0x0) at continuations.c:325 #15 0x00007fccbed49881 in scm_c_with_continuation_barrier (func=0x7fccbedcedf4 <really_launch>, data=0x7fff6d32ca30) at continuations.c:367 #16 0x00007fccbedced99 in scm_i_with_guile_and_parent (func=0x7fccbedcedf4 <really_launch>, data=0x7fff6d32ca30, parent=0xb2f380) at threads.c:733 #17 0x00007fccbedceef0 in launch_thread (d=0x7fff6d32ca30) at threads.c:788 #18 0x00007fccbe1d08ba in start_thread (arg=<value optimized out>) at pthread_create.c:300 #19 0x00007fccbdf3802d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #20 0x0000000000000000 in ?? ()
; Show how a deadlock can occur when forking a new thread (use-modules (ice-9 popen) (ice-9 threads)) (define (repeat n f) (if (> n 0) (begin (f) (repeat (- n 1) f)))) (define (forever f) (f) (forever f)) (display "Spawn a thread that performs some writes\n") (make-thread forever (lambda () (display "write...\n"))) (display "Now exec some processes...\n") (forever (lambda () (let ((pipe (open-input-pipe "sleep 0"))) (close-pipe pipe))))
; A small variation that crash (use-modules (ice-9 threads)) (define (forever f) (f) (forever f)) ; Spawn a thread that performs some writes (make-thread forever (lambda () (display "write...\n"))) (forever (lambda () (display "new pipe...\n")))