www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - dmd -run fails with Nix on macOS Mojave

reply Thomas Mader <thomas.mader gmail.com> writes:
On macOS Mojave dmd built with Nix can not be used with the -run 
parameter.

dmd -run hello.d
/var/tmp/dmd_runNVSCJp: Permission denied
core.thread.ThreadError core/thread.d(3206): Unable to load 
thread state

A normal compile and run works and it used to work before I 
upgraded to Mojave.
I checked the official dmd binary for macOS and everything works 
there.
It seems to be a problem with Nix in connection with Mojave.

I came here to ask for hints.

It's dmd 2.084.1 and the line number of the ThreadError is not 
right. I don't know why.

I don't know what the compiler wants to write to 
/var/tmp/dmd_runNVSCJp and why that fails with a Permission 
denied.
Feb 19
next sibling parent reply Thomas Mader <thomas.mader gmail.com> writes:
On Tuesday, 19 February 2019 at 20:32:32 UTC, Thomas Mader wrote:
 I don't know what the compiler wants to write to 
 /var/tmp/dmd_runNVSCJp and why that fails with a Permission 
 denied.
Ok I found it, it's created in link.d
Feb 19
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Tuesday, 19 February 2019 at 20:37:48 UTC, Thomas Mader wrote:
 On Tuesday, 19 February 2019 at 20:32:32 UTC, Thomas Mader 
 wrote:
 I don't know what the compiler wants to write to 
 /var/tmp/dmd_runNVSCJp and why that fails with a Permission 
 denied.
Ok I found it, it's created in link.d
Not sure if macos does this, but on linux you can mount directories as "noexec" which means you can't run executables that live inside those mounts. On linux you could check this with "mount | grep /var/tmp", not sure if it's the same on MacOS. (Related Issue: https://github.com/dragon-lang/rund/issues/17)
Feb 19
parent reply Thomas Mader <thomas.mader gmail.com> writes:
On Tuesday, 19 February 2019 at 21:06:29 UTC, Jonathan Marler 
wrote:
 On Tuesday, 19 February 2019 at 20:37:48 UTC, Thomas Mader 
 wrote:
 On Tuesday, 19 February 2019 at 20:32:32 UTC, Thomas Mader 
 wrote:
 I don't know what the compiler wants to write to 
 /var/tmp/dmd_runNVSCJp and why that fails with a Permission 
 denied.
Ok I found it, it's created in link.d
Not sure if macos does this, but on linux you can mount directories as "noexec" which means you can't run executables that live inside those mounts. On linux you could check this with "mount | grep /var/tmp", not sure if it's the same on MacOS. (Related Issue: https://github.com/dragon-lang/rund/issues/17)
No that's not the problem. Nix does not change mounts when a binary is run. All it's doing is specify it's own directories and this also includes the System Libs of macOS. That's also the reason why official dmd package still works as all Nix stuff is contained in one directory and is only used by Nix executables. Probably it's something with the C environment. With this I could explain the thread error but the permission denied leaves me clueless because the directory is clearly writable. I also already tried to patch link.d so P_tmpdir is not used anymore but a custom dir I defined but it did not change anything.
Feb 19
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Tuesday, 19 February 2019 at 21:27:19 UTC, Thomas Mader wrote:
 On Tuesday, 19 February 2019 at 21:06:29 UTC, Jonathan Marler 
 wrote:
 On Tuesday, 19 February 2019 at 20:37:48 UTC, Thomas Mader 
 wrote:
 On Tuesday, 19 February 2019 at 20:32:32 UTC, Thomas Mader 
 wrote:
 I don't know what the compiler wants to write to 
 /var/tmp/dmd_runNVSCJp and why that fails with a Permission 
 denied.
Ok I found it, it's created in link.d
Not sure if macos does this, but on linux you can mount directories as "noexec" which means you can't run executables that live inside those mounts. On linux you could check this with "mount | grep /var/tmp", not sure if it's the same on MacOS. (Related Issue: https://github.com/dragon-lang/rund/issues/17)
No that's not the problem. Nix does not change mounts when a binary is run. All it's doing is specify it's own directories and this also includes the System Libs of macOS.
Yes I'm pretty familair with how Nix works. I'm not talking about Nix changing mount settings or installing files in places it shouldn't, I'm talking about where dmd stores the executable its going to run. Of course I don't know if this is the issue you're running into, but if it is then it's not necessarily a problem with Nix, it could just be a configuration issue with DMD as to where it store temporary executables.
Feb 19
parent reply Thomas Mader <thomas.mader gmail.com> writes:
On Tuesday, 19 February 2019 at 21:34:30 UTC, Jonathan Marler 
wrote:
 Yes I'm pretty familair with how Nix works.  I'm not talking 
 about Nix changing mount settings or installing files in places 
 it shouldn't, I'm talking about where dmd stores the executable 
 its going to run.  Of course I don't know if this is the issue 
 you're running into, but if it is then it's not necessarily a 
 problem with Nix, it could just be a configuration issue with 
 DMD as to where it store temporary executables.
I ruled out that idea by now because: - I changed dmd to use a tmpdir I created in the home dir of the running user and I got the same error. - If the temporary file can not be created I think that dmd should output a dedicated error message: https://github.com/dlang/dmd/blob/6151bf8bfb21416b5857a64ab7fd8ae318ca02fb/src/dmd/link.d#L464 - The ThreadError seems to be connected to fork and the call to fork comes after the creation of the file in runLINK I never tried to debug dmd with a debugger but I think it's time to start.
Feb 19
next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Tuesday, 19 February 2019 at 22:07:58 UTC, Thomas Mader wrote:
 On Tuesday, 19 February 2019 at 21:34:30 UTC, Jonathan Marler 
 wrote:
 [...]
I ruled out that idea by now because: - I changed dmd to use a tmpdir I created in the home dir of the running user and I got the same error. - If the temporary file can not be created I think that dmd should output a dedicated error message: https://github.com/dlang/dmd/blob/6151bf8bfb21416b5857a64ab7fd8ae318ca02fb/src/dmd/link.d#L464 - The ThreadError seems to be connected to fork and the call to fork comes after the creation of the file in runLINK I never tried to debug dmd with a debugger but I think it's time to start.
Not sure if Mac has an equivalent to "strace", but if it does than that's a really easy first step. See which system call actually failed and get the error code.
Feb 19
parent sarn <sarn theartofmachinery.com> writes:
On Tuesday, 19 February 2019 at 23:05:22 UTC, Jonathan Marler 
wrote:
 Not sure if Mac has an equivalent to "strace", but if it does 
 than that's a really easy first step.  See which system call 
 actually failed and get the error code.
Mac OS X has DTrace instead of strace. https://8thlight.com/blog/colin-jones/2015/11/06/dtrace-even-better-than-strace-for-osx.html (+1 to syscall tracing being faster than a debugger for this kind of problem.)
Feb 19
prev sibling parent reply Thomas Mader <thomas.mader gmail.com> writes:
I now know a little bit more. It fails at [1] and after the 
d_do_test.d object is created with:

/private/var/folders/wq/m1dnr42s42n5msqk2v8l0lfc0000gn/T/nix-build-dmd-2.084.1.drv-49/dmd/generate
/osx/release/64/dmd -conf= -m64 -fPIC -g -unittest -run tools/d_do_test.d

the linking part in the newly created process with fork fails. 
This is the linking command:

clang++ d_do_test.o -o /var/tmp/dmd_runNGJfCU -g -m64 -Xlinker 
-no_compact_unwind -L../../phobos/generated/osx/release/64 
-lphobos2 -lpthread -lm

The file /var/tmp/dmd_runNGJfCU is created with rw permissions 
for my user.

If I replace the "childpid = fork();" line with "childpid = 0;" 
it works.
So there seems to be something wrong with the permissions of the 
child process.

[1] 
https://github.com/dlang/dmd/blob/73fcf82ae1d6f0582c19e8c2ae0d09f319745521/src/dmd/link.d#L692
Feb 23
parent Thomas Mader <thomas.mader gmail.com> writes:
On Saturday, 23 February 2019 at 18:54:09 UTC, Thomas Mader wrote:
 I now know a little bit more. It fails at [1] and after the 
 d_do_test.d object is created with:

 /private/var/folders/wq/m1dnr42s42n5msqk2v8l0lfc0000gn/T/nix-build-dmd-2.084.1.drv-49/dmd/generate
/osx/release/64/dmd -conf= -m64 -fPIC -g -unittest -run tools/d_do_test.d

 the linking part in the newly created process with fork fails.
Yeah and I was so wrong about that. Clearly the execution of the program failed ( https://github.com/dlang/dmd/blob/73fcf82ae1d6f0582c19e8c2ae0d09f319745521 src/dmd/link.d#L905 ) not the linking part. The problem is that for whatever reason, Nix's clang does not add executable rights if the output file was already created without executable rights. I created https://github.com/NixOS/nixpkgs/issues/57120 .
Mar 09
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-02-19 21:32, Thomas Mader wrote:
 On macOS Mojave dmd built with Nix can not be used with the -run parameter.
 
 dmd -run hello.d
 /var/tmp/dmd_runNVSCJp: Permission denied
 core.thread.ThreadError core/thread.d(3206): Unable to load thread state

 I don't know what the compiler wants to write to /var/tmp/dmd_runNVSCJp 
 and why that fails with a Permission denied.
I had the same issue on FreeBSD (TrueOS actually), because it's /tmp is mounted as "noexec". But that's usually not the case on macOS. -- /Jacob Carlborg
Feb 22