gittup / tup

Tup is a file-based build system.
http://gittup.org/tup/
GNU General Public License v2.0
1.17k stars 144 forks source link

Broken pipe when compiling nimrod programs on Windows #80

Open zah opened 12 years ago

zah commented 12 years ago

I get the following error when trying to use the nimrod compiler on Windows (it works fine on other platforms):

[ ]   0%.tup/tmp/output-98: Broken pipe
tup error: Unable to open sub-process output file after the process completed.
 *** Command ID=98 failed: nimrod.exe c hello.nim

 [ ]   0%
 *** tup: 1 job failed.

Nimrod is one of those compilers that compiles the code to C and then calls some external C compiler like gcc or cl to finish the build. I get the same error regardless of which external compiler is used and using gcc or cl directly with tup works fine. The code that is used to launch the external compiler can be found here: https://github.com/Araq/Nimrod/blob/master/lib/pure/osproc.nim#L421 (This is written in nimrod, but the translation to C should be pretty straight-forward)

Tupfile:

: hello.nim |> nimrod c --nimcache:".nimcache" %f |> %B.exe

hello.nim

echo "hello"
zah commented 12 years ago

I forgot to add another important detail. The external compiler process remains suspended after the error with a single thread stopped at: ntdll.dll!RtlUserThreadStart

gittup commented 12 years ago

On Tue, Aug 14, 2012 at 3:44 AM, zah notifications@github.com wrote:

I get the following error when trying to use the nimrodhttp://nimrod-code.org/compiler on Windows (it works fine on other platforms):

[ ] 0%.tup/tmp/output-98: Broken pipe tup error: Unable to open sub-process output file after the process completed. *\ Command ID=98 failed: nimrod.exe c hello.nim

[ ] 0% *\ tup: 1 job failed.

Nimrod is one of those compilers that compiles the code to C and then calls some external C compiler like gcc or cl to finish the build. I get the same error regardless of which external compiler is used and using gcc or cl directly with tup works fine. The code that is used to launch the external compiler can be found here: https://github.com/Araq/Nimrod/blob/master/lib/pure/osproc.nim#L421 (This is written in nimrod, but the translation to C should be pretty straight-forward)

Tupfile:

: hello.nim |> nimrod c --nimcache:".nimcache" %f |> %B.exe

hello.nim

echo "hello"

— Reply to this email directly or view it on GitHubhttps://github.com/gittup/tup/issues/80.

It seems the DLL injection was dying because the process name argument in CreateProcess is NULL. Tup was using a strcmp on it to check if it's mspdbsrv.exe and ignore it, since that is started by the VS toolchain and is a daemon process. I'm not sure why it's NULL, but merely skipping the check in that case seems to work.

It doesn't seem to work without the nimcache, since it deletes temporary files in a weird way. Instead of calling DeleteFile, it calls SetDispositionInformationFile (according to ProcMon, I think this corresponds to NtSetInformationFile). However, when I try to hook NtSetInformationFile, tup dies.

Can you confirm that your example now works?

$ tup upd [ tup ] [0.000s] Scanning filesystem... [ tup ] [0.062s] Reading in new environment variables... [ tup ] [0.062s] No Tupfiles to parse. [ tup ] [0.062s] No files to delete. [ tup ] [0.062s] Executing Commands... 100% 1) [0.375s] nimrod c --nimcache:".nimcache" hello.nim Hint: used config file 'C:\Program Files (x86)\Nimrod\config\nimrod.cfg' [Conf] Hint: system [Processing] Hint: hello [Processing] gcc.exe -o c:\cygwin\home\marf\nimrod-test\hello.exe .nimcache\hello.o .nimcache\nim__dat.o .nimcache\system.o Hint: operation successful (6631 lines compiled; 0.344 sec total; 6.614MB) [SuccessX] [ tup ] [0.453s] Updated. $ ./hello.exe hello

Thanks, -Mike

gittup commented 12 years ago

On Tue, Aug 14, 2012 at 9:22 AM, zah notifications@github.com wrote:

I forgot to add another important detail. The external compiler process remains suspended after the error with a single thread stopped at: ntdll.dll!RtlUserThreadStart

— Reply to this email directly or view it on GitHubhttps://github.com/gittup/tup/issues/80#issuecomment-7725449.

Yeah, tup intercepts CreateProcess and starts all new processes as suspended so that they can be injected with the DLL. However, since the injection was crashing, the process would never be resumed. Let me know if you find additional errors like this.

Thanks! -Mike

zah commented 12 years ago

Thanks Mike. Works fine now.

Besides the error you mentioned, setting nimcache to a hidden directory is required in order to avoid specifying the multiple outputs nimrod will create during compilation (these are C source files and compiled obj files so they are not strictly temporary).

zah commented 12 years ago

This is again broken on Windows 8, but with a twist. Tup doesn't detect outputs created by the spawned process. (Again stand-alone use of gcc or cl works fine, but both fail when spawned from nimrod)

Hint: operation successful (7287 lines compiled; 0.859 sec total; 6.666MB) [SuccessX]
 *** tup errors ***
tup warning: Writing to hidden file 'C:\Users\Zahary\Work\Scratch\nimrod\.nimcache\test.c'
tup warning: Writing to hidden file 'C:\Users\Zahary\Work\Scratch\nimrod\.nimcache\system.c'
tup error: Expected to write to file 'test.exe' from cmd 37 but didn't
 *** Command ID=37 ran successfully, but tup failed to save the dependencies.

You probably don't have a Windows 8 machine ready for testing so can you suggest how can I help you debug this further?