www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Hangs on toStringZ()

reply unDEFER <undefer gmail.com> writes:
Hello I have very simple line with exec-command:

execl("/bin/bash".toStringz(), "/bin/bash".toStringz(), 
"-c".toStringz(), command.toStringz(), null);

And on this line on toStringz my program sometimes hangs.
backtrace:

(gdb) bt

../sysdeps/unix/syscall-template.S:84

core.thread.Thread.sleep(core.time.Duration) ()

core.internal.spinlock.SpinLock.yield(ulong) shared
     ()

shared ()

gc.gc.GC.runLocked!(gc.gc.GC.mallocNoSync(ulong, uint, ref ulong, 
const(TypeInfo)), gc.gc.mallocTime, gc.gc.numMallocs, ulong, 
uint, ulong, const(TypeInfo)).runLocked(ref ulong, ref uint, ref 
ulong, ref const(TypeInfo)) ()

const(TypeInfo))
     ()


const(TypeInfo), const(TypeInfo)) ()




std.string.toStringz(const(immutable(char)[])) ()

unde.command_line.run.fork_command(unde.global_state.CMDGlobalState,
immutable(char)[], immutable(char)[], std.concurrency.Tid) (
     tid=..., command=..., cwd=..., cgs=0x7f3abcdffb80)
     at source/unde/command_line/run.d:2002

What is it? For what it waits?
Dec 27 2016
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 27 December 2016 at 17:27:14 UTC, unDEFER wrote:
 Hello I have very simple line with exec-command:

 execl("/bin/bash".toStringz(), "/bin/bash".toStringz(), 
 "-c".toStringz(), command.toStringz(), null);

 [...]
The string is allocated on the gc-ed heap. And since it's an R value it might get destroyed before execl is finished. Assign the result of toStringz to a char* variable and use that in the call.
Dec 27 2016
parent reply unDEFER <undefer gmail.com> writes:
On Tuesday, 27 December 2016 at 17:50:14 UTC, Stefan Koch wrote:
 The string is allocated on the gc-ed heap.
 And since it's an R value it might get destroyed before execl 
 is finished.
 Assign the result of toStringz to a char* variable and use that 
 in the call.
But execl not goes to Seg.fault. It hangs before call execl..
Dec 27 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 27 December 2016 at 18:00:11 UTC, unDEFER wrote:
 On Tuesday, 27 December 2016 at 17:50:14 UTC, Stefan Koch wrote:
 The string is allocated on the gc-ed heap.
 And since it's an R value it might get destroyed before execl 
 is finished.
 Assign the result of toStringz to a char* variable and use 
 that in the call.
But execl not goes to Seg.fault. It hangs before call execl..
Have you tried assigning it to a variable ?
Dec 27 2016
parent reply unDEFER <undefer gmail.com> writes:
On Tuesday, 27 December 2016 at 18:01:36 UTC, Stefan Koch wrote:
 Have you tried assigning it to a variable ?
Yes, I have tried, now backtrace of hanged process is: (gdb) bt
Dec 27 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 27 December 2016 at 18:22:12 UTC, unDEFER wrote:
 On Tuesday, 27 December 2016 at 18:01:36 UTC, Stefan Koch wrote:
 Have you tried assigning it to a variable ?
Yes, I have tried, now backtrace of hanged process is: (gdb) bt
BTW, if you are using literals the toStringZ call is not needed. They are zero terminated by default.
Dec 27 2016
parent unDEFER <undefer gmail.com> writes:
The last backtrace shows that it hangs on the line:

immutable(char) *bash = "/bin/bash".toStringz();
Dec 27 2016
prev sibling next sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Tuesday, 27 December 2016 at 17:27:14 UTC, unDEFER wrote:
 Hello I have very simple line with exec-command:

 execl("/bin/bash".toStringz(), "/bin/bash".toStringz(), 
 "-c".toStringz(), command.toStringz(), null);

 And on this line on toStringz my program sometimes hangs.
 backtrace:

 (gdb) bt

 ../sysdeps/unix/syscall-template.S:84

 core.thread.Thread.sleep(core.time.Duration) ()

 core.internal.spinlock.SpinLock.yield(ulong) shared
     ()

 core.internal.spinlock.SpinLock.lock() shared ()

 gc.gc.GC.runLocked!(gc.gc.GC.mallocNoSync(ulong, uint, ref 
 ulong, const(TypeInfo)), gc.gc.mallocTime, gc.gc.numMallocs, 
 ulong, uint, ulong, const(TypeInfo)).runLocked(ref ulong, ref 
 uint, ref ulong, ref const(TypeInfo)) ()

 const(TypeInfo))
     ()


 const(TypeInfo), const(TypeInfo)) ()




 std.string.toStringz(const(immutable(char)[])) ()

 unde.command_line.run.fork_command(unde.global_state.CMDGlobalState,
immutable(char)[], immutable(char)[], std.concurrency.Tid) (
     tid=..., command=..., cwd=..., cgs=0x7f3abcdffb80)
     at source/unde/command_line/run.d:2002

 What is it? For what it waits?
What context are you calling this from? Is this in a signal handler? Or from inside a destructor of a GC-owned object?
Dec 27 2016
parent unDEFER <undefer gmail.com> writes:
On Tuesday, 27 December 2016 at 21:33:46 UTC, Marc Schütz wrote:

 What context are you calling this from? Is this in a signal 
 handler? Or from inside a destructor of a GC-owned object?
It is child of my process after fork and before execl. No signal handler, no destructor, no catch-block, usual code.
Dec 27 2016
prev sibling parent reply Nemanja Boric <4burgos gmail.com> writes:
On Tuesday, 27 December 2016 at 17:27:14 UTC, unDEFER wrote:
 Hello I have very simple line with exec-command:

 execl("/bin/bash".toStringz(), "/bin/bash".toStringz(), 
 "-c".toStringz(), command.toStringz(), null);

 [...]
Just a note here, string literals are already 0 terminated, so you don't need `toStringz` there.
Dec 28 2016
parent reply Nemanja Boric <4burgos gmail.com> writes:
On Wednesday, 28 December 2016 at 11:21:34 UTC, Nemanja Boric 
wrote:
 On Tuesday, 27 December 2016 at 17:27:14 UTC, unDEFER wrote:
 Hello I have very simple line with exec-command:

 execl("/bin/bash".toStringz(), "/bin/bash".toStringz(), 
 "-c".toStringz(), command.toStringz(), null);

 [...]
Just a note here, string literals are already 0 terminated, so you don't need `toStringz` there.
Ah, I just saw Stefan already made this remark, sorry. Given that you're in a forked process, it could be that you've just got your GC in a broken state (internal was locked prior to forking, and now you can't get the GC ever, since there's nothing to unlock it. What you should do is following: 1. Allocate all needed data, convert all D strings into C strings, etc. 2. fork 3. exec immediately, not using anything from standard library between 2 and 3.
Dec 28 2016
next sibling parent reply Nemanja Boric <4burgos gmail.com> writes:
On Wednesday, 28 December 2016 at 11:30:22 UTC, Nemanja Boric 
wrote:
 On Wednesday, 28 December 2016 at 11:21:34 UTC, Nemanja Boric 
 wrote:
 On Tuesday, 27 December 2016 at 17:27:14 UTC, unDEFER wrote:
 [...]
Just a note here, string literals are already 0 terminated, so you don't need `toStringz` there.
Ah, I just saw Stefan already made this remark, sorry. Given that you're in a forked process, it could be that you've just got your GC in a broken state (internal was locked prior to forking, and now you can't get the GC ever, since there's nothing to unlock it. What you should do is following: 1. Allocate all needed data, convert all D strings into C strings, etc. 2. fork 3. exec immediately, not using anything from standard library between 2 and 3.
My other guess is that you're using D threads in your application?
Dec 28 2016
parent reply unDEFER <undefer gmail.com> writes:
On Wednesday, 28 December 2016 at 11:32:09 UTC, Nemanja Boric 
wrote:
 My other guess is that you're using D threads in your 
 application?
Of course I'm using D threads, but with it all is normally.
Dec 28 2016
parent reply Nemanja Boric <4burgos gmail.com> writes:
On Wednesday, 28 December 2016 at 12:30:03 UTC, unDEFER wrote:
 On Wednesday, 28 December 2016 at 11:32:09 UTC, Nemanja Boric 
 wrote:
 My other guess is that you're using D threads in your 
 application?
Of course I'm using D threads, but with it all is normally.
Right, nothing wrong with threads, but super tricky to combine it with fork. So, it could be that one of your threads is using GC at the point of the forking, so it keeps the GC locked. Now you fork, and _all your threads don't exist anymore, they are vanished, and if you don't do some clever stuff in atfork handler, there will be no cleanup_ - you just have copy of the thread that called fork. So, the thread that should release GC lock doesn't exist anymore, and there's nothing to release mutex, and it will stay locked forever in your forked process.
Dec 28 2016
parent unDEFER <undefer gmail.com> writes:
On Wednesday, 28 December 2016 at 12:39:46 UTC, Nemanja Boric 
wrote:
 Right, nothing wrong with threads, but super tricky to combine 
 it with fork. So, it could be that one of your threads is using 
 GC at the point of the forking, so it keeps the GC locked. Now 
 you fork, and _all your threads don't exist anymore, they are 
 vanished, and if you don't do some clever stuff in atfork 
 handler, there will be no cleanup_ - you just have copy of the 
 thread that called fork. So, the thread that should release GC 
 lock doesn't exist anymore, and there's nothing to release 
 mutex, and it will stay locked forever in your forked process.
Thanks a lot for such detailed explanation!
Dec 28 2016
prev sibling parent unDEFER <undefer gmail.com> writes:
On Wednesday, 28 December 2016 at 11:30:22 UTC, Nemanja Boric 
wrote:
 What you should do is following:

 1. Allocate all needed data, convert all D strings into C 
 strings, etc.
 2. fork
 3. exec immediately, not using anything from standard library 
 between 2 and 3.
OK, thank you.. I'm trying it and still haven't hanging.
Dec 28 2016