CFA: pseudo-reloc v2

Christopher Faylor
Mon Oct 5 06:13:00 GMT 2009

On Mon, Oct 05, 2009 at 01:07:51AM -0400, Charles Wilson wrote:
>Corinna wrote:
>>Here's another idea.  At one point Brian Dessent proposed a patch to
>>detect a missing DLL.  Hmm, yes, here's the checkin of your patch
>>implementing that, back on 2008-03-26.
>>I was wondering if a similar technique could be used to print an error
>>message in the parent process, if the relocation failed in the child
>>process.  The idea would be to generate a specific status code which
>>would then catched in status_exit, just like STATUS_DLL_NOT_FOUND.
>One downside of using WriteConsole[W] is that you'll never see the
>message if you're running in a terminal other than cmd.exe, nor if
>you're launching the app via a shortcut.  The output will go to the
>"invisible" console allocated by cygwin, right?

Yes.  The same thing will happen if you have cygwin1.dll catch the
error.  Actually, I really meant that we should use WriteFile, not
WriteConsole.  Otherwise you won't be able to redirect stderr.

>> I'm just not sure how to generate that specific status code...
>Yeah, that...
>cgf suggests ExitProcess. I tried that, but the process hangs when it
>calls that function. I think this has to do with the fact that
>ExitProcess goes back thru the loaded DLL list and tries to call the
>entry points with DLL_PROCESS_DETACH. But, since the (current) DLL is
>Now, TerminateProcess seems to work -- but then NONE of the DLLs get
>notified. Oh -- and it hangs if you strace within any terminal except
>cmd.exe; the strace output is identical in the two cases, but the
>non-cmd one has this extra line at the end:
>29661   30435 [sig] crtest_v1 4692 wait_sig: entering ReadFile loop,
>my_readsig 0x17C, my_sendsig 0x180
>and then it hangs.

If the dynamic loading is being done during DLL initialization that
makes sense.  It's a deadlock situation.

>> Other than that, I have no problems to use WriteConsole.
>So...maybe something like the following?  This is a diff against the
>current mingw/pseudo-reloc.c.  The "normal" code path (that is, none of
>the error conditions are hit) works fine.
>The rest of this email is about the error cases.
>I tested the error path by reversing the test at line 110. In an rxvt
>window, I got the following behavior:
>$ ./crtest_v2.exe
>$ echo $?
>In a cmd.exe window, this is what I observerd:
>$ ./crtest_v2.exe
>Relocation error: bad address specified 0x00401139.
>$ echo $?
>I also attempted to modify and bits following Dave's
>suggestion, partly so that these reloc errors would result in a 127 exit
>code, just like cgf/brian's mod for STATUS_DLL_NOT_FOUND.  But I
>couldn't get it to "trigger" -- I didn't get the error message I
>specified in, and I still got an exit code 0, not 127.  Then, I
>tried this:
>--------------- foo.c -----------------
>#include <stdio.h>
>#include <windows.h>
>#include <ntdef.h>
>#define STATUS_DLL_NOT_FOUND          ((NTSTATUS) 0xc0000135)
>int main(int argc, char* argv[])
>  TerminateProcess (GetCurrentProcess(), STATUS_ILLEGAL_DLL_RELOCATION);
>  exit (1);
>With cygwin1.dll having the modified pinfo/sigproc, and launching this
>test program from bash, I would *expect* to see the message from my
>patched "foo.exe: error while loading shared libraries: ?:
>cannot open shared object file: illegal relocation" (there's a '?'
>because this silly test program doesn't have an 'unloaded DLL' name to
>put there).
>If I understand the pinfo code, it's actually the *parent* process that
>receives the err code >= 0xc0000000, and prints the
>DLL_NOT_FOUND/ILLEGAL_DLL_RELOCATION error message.  That is, bash.

Well, yes.  TerminateProcess wouldn't work too well as a method for
communicating status values otherwise.

>$ gcc -o foo.exe foo.c
>$ ./foo.exe
>$ echo $?
>(NOT 127, and NOT 1 !)
>But, if I use gcc-3 -mno-cygwin:
>$ gcc-3 -mno-cygwin -o foo.exe  foo.c
>$ ./foo.exe
>/usr/src/devel/kernel/pseudo-reloc-tests/test-app/foo.exe: error while
>loading shared libraries: ?: cannot open shared object file: illegal
>$ echo $?

The above illustrates why WriteFile is a good idea.  You presumably know
the name of the shared library at that point and can print it rather than
having cygwin1.dll print "?".

>which is what I expected to see in all cases.  Just to verify that it is
>not a gcc-3/gcc-4 thing:
>$ gcc-3 -o foo.exe  foo.c
>$ ./foo.exe
>$ echo $?
>So, it's a "cygwin" thing: if the child is a cygwin app, then the
>pinfo::maybe_set_exit_code_from_windows --> status_exit() code path is
>NOT hit at all.  That's just weird. Help?

I am too tired to look at the code right now but, as I recall, there is
currently no reason for Cygwin to retrieve the windows exit code from a
known Cygwin app.  So this isn't really surprising.


More information about the Cygwin-developers mailing list