This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug: C-prog from Win dies in fork; gdb.exe also won't run


Brian Dessent wrote:
Linda Walsh wrote:

        Perhaps -- you don't, but my first symptom of a problem was a simple cygwin
program refusing to run from cmd.exe.  At the same time, I'm having
problems with 'bash' (or 'ash') as launched from windows as well -- in both
cases, the programs "used to work", and now I see a cmd-window come up,

I agree that it is potentially a bug if fork() spews errors, unless of
course it is being molested by some kind of BLODA type of interference.
===
	It is Windows.  It's most certainly being molested. I don't know
anyone named BLODA.  Was he the guy responsible for blowing off YODA?
(don't know of any dark-side sys-call interfering progs either, but I
admit to not being up on my latest knowledge of dark-siders).

However that is a different issue than the one that is the subject of
this message -- I still think we're talking about two totally unrelated
phenomina.
----
	Willing to grant you that.  Just coincidental that the fork
"behavior" (how's that...) or however you spawn it is at the heart of
the matter in both cases, though one's from a lack of proper fork
etiquette, while the other's more choking on cygwin's imitation of
a fork.

        So I'll go back to my first posted problem.  Why can't I fork when
running from cmd.exe if the binary I am running is in "\windows" or
"\windows\system32"  I'm not aware of there being special cases for \windows
or \windows\system32 in Posix either.  The Cygwin "bin" dir is first in my
path, so cygwin libraries should be accessible via the path.

I'm still not clear on the details here.
---
	Not clear?!  With my elegant, concise and crystal description!?!
But but but...it's on windows, so it has to be clear.  (hey...if you can
non sequitur, so can I).


You have a Cygwin wrapper
program that forks and execs a native Win32 binary, then itself exits.

This fails with fork errors if the wrapper is located in %windir% but
works otherwise?
---
	Well fails if in %windir%, or %windir%/system32 (originally ran
into it when I tried putting in the <sys32> dir, but doesn't work in
"/windows" either.

But also -- and this is important -- only fails if called
directly by a Windows App. (no intervening cygwin program). I first
ran into it when I was in (1)"WinZip (the GUI)" and opened a text file.
A slight flicker of a CMD window with some hastily spit out error text,
and the window closes...all in about a 3ms. Just slightly shorter than
my attentionspan...or rather ability to read even 1 word in the
window-blink. (2) Next tried same command in a Bash window. That worked
"properly. (3) Next: start "cmd.exe" in the 'Bash' window (cmd launched -!-
'spawned' by bash...(that's just wrong...bash spawning win cmd.exe's ... *shiver*)). That worked -- no furking errors. (4) Next tried
launching gvim on a ".txt" file sitting on my Desktop (so in ~/Desktop).
Tried filenames (4a) with and (4b) without spaces in the filename,
as I didn't know if that was related. Both gave me the flickering
cmd window with some err-text in it (no help).


	So tried (5)'Run' -- another 'flicker' cmd window.  Then
tried running a (6) cmd.exe window direct from win (no intervening
bash or cygwin 'protection' layer).  That duplicated the error message
in a non-disappearing window!  Progress!  It would give the error
when invoking the program from either of the win dirs (win or sys32).
The CWD seems to make no difference -- just the location of the binary
file.

	So I wondered if the binary was munged.  Went to the source dir
where I had a copy of the "application" in question (the redirector).
The md5's of the binaries (in /win, ..sys32, my appdir ("~/c/gvim"),
were all the same.  (6) Running the app under cmd.exe worked in my appdir.

(7) I tried recompiling it; ("cc -Os gvim.c -s -o gvim.exe") -- making sure
I had binary corresponding to  source.  Named it "mygvim.exe".  It
(7a) worked in my appdir, but if I copied it to and ran it in
either of the winsys dirs (7b,c)(/win...or ../system32), it would
fail.

	Next I verified (8) ash and (9) tcsh by invoking both from
cmd.exe, then running the failure cases -- both locations.  Both
locations worked with both shells.  So running any cygwin shell
before running the "app", makes the fork problem "go away".

	Of course, running with strace (10) also "works" (spawns
gvim window and exits).

	HOWEVER...attempting to run (11) "gdb" on mygvim FAILS, but in
a different way.  May be a different bug, but it is *related*.

	If I run (12) gdb directly on top of cmd.exe, (doesn't
seem to matter what dir, it never gets to the program name).  In
fact, just invoking "gdb" directly under cmd gives a popup error
window: "The application failed to initialize properly (0xc0000022).
Click on OK to terminate the appliction".  Trying to strace gdb
also gives an immediate failure:

C:\bin>strace gdb.exe
--- Process 3600, exception C0000022 at 7C964ED1

There...now you've done it. You had me break 'gdb'.



Does it work if you use a native (MinGW) wrapper that
consists of just _execv("c:/path/to/vim.exe", argv)?  What about a
simple shell wrapper that consists of "#!/bin/sh\ncygstart
/path/to/vim"?
----
	The shell wrapper is going to work since it involves a cygwin
shell layer.  I'm 90% certain that the native _execv will work, since
I have had no problems once I get past the fork...but...(getting out
x86-abacus..) and changing only 1 thing at a time:
using:
char * const path="/Prog/Vim/gvim.exe";
execv(path,argv);
fprintf(stderr, "Error exec'ing %s, errno=%d\n",path,errno);
exit(2);
//      }
// parent, hopefully, quietly exits....
exit(0);
--------
	"works" with no error message displayed".  I could try a
mingw version too, but since the cygwin version works, I'd be even
more confident (98%) that it would work as well ....


That is a "non-sequitur".

Okay, let me rephrase: Often software that has a native Win32 port will contain remnants of Unix terminology or features that do not work.
---
	Ah, thank you...separated by a common language...I tend to still
use fork as a verb on windows, even though I've known, at least since
the "90's" that Windows required spawning instead of forking to
get a new process (and also, to get a "TRUE" fork, would be a
a royal pain, involving duplicating all of the user's address space
and creating a clone of the process -- basically writing all of the
machinery of 'fork' manually -- not even being able to rely on
paging in of files based off of "open" file descriptors, since
MS-Win does it's binary locking based on disk-sectors.  You'd
have to find all of the current process's  open files (open for
being paged from, and their current name on disk (which may have
changed since starting the original program, as "rename" works on
active libraries and executables.  I haven't done it, but can
imagine it would be a major pain to get right.


Process creation on Windows is centered around the notion of creating a
new process with new PID and completely separate VM address space.  I'll
call this primitive *spawning* from here on to avoid confusion.
---
	Ug...I really don't like fish that much.  Between that and "spawn
of the devil", it hasn't ever been a favorite syscall.


"in the background" is not a very precise technical term.  In Win32,
when spawning a child the parent gets to choose:

....
- whether to wait and block on the child terminating or to continue
executing independently
Note the last point is I think the crutial one here: it's the parent
that decides whether to wait or continue.  The child has no control over
the behavior of the parent.
----
	The child doesn't have much control over the parent on linux
either.  The parent can wait or not, can choose what to share (via clone),
etc.


But as to "forking", what specifically does not exist anywhere in Win32,
and what Cygwin has to go through enormous hoops to emulate, is the
notion of *replacing* one process by another (exec) or *duplicating* one
process into two (fork).  These have very different semantics than
spawning a new process, so that's why I find it very wrong to say that a
native Win32 program does anything resembling a "fork".
----
	I hear what you are saying...yet did you know that MS
improved fork and exec performance by 30% in their SFU Unix-compat layer?
:-).  I wonder what 'pains' they go through -- they might have it
easier and just use straight NT calls rather than Win32.  Dunno...


The exec() that Windows does have is just an elaboration of *spawning*
followed by the parent *exiting*.  On the surface this may seem to be
the same as the POSIX exec but it's not -- the main difference being
that the child has a new and distinct PID as well as potentially other
per-process attributes[1].  In other words, the child was created as a
separate and new process, it did not take over in the shoes of the
parent.
===
	Good point...exec doesn't change the PID.


I'm pretty sure the "&" addendum in cmd.exe does something similar to this
within cmd.  The functionality seems to be there despite that the function
may not be called "fork" nor have the exact same semantics of "fork".

I think you're conflating what the parent does after the new process has
been created (i.e. whether to wait and block on the child to terminate
or not) with how the process was created.
---
	Since "Cmd.exe" is mostly a "blackbox" to me, any behavior
occurring within Cmd, that "looks like" similar behavior in a linshell,
is likely to be 'conflated.  I don't know if cmd uses the 10-argument
"CreateProcess", or does a "_spawnX(NOWAIT, prog, args....)".


It is not immediately evident where the splitting of the GUI
process off into the background is done: whether in in cmd.exe or
every windows program that can interactively launch processes,
or in the processes themselves.

I'm not sure I follow. Say you are a Win32 GUI executable.
---
	I'll try not to be insulted. :-)

You start
up, you create your windows, you interact with the user. At no point do
you control anything about the process that created you. Whether it
wants to wait or not for you to terminate is not something you (vim in
this case) have any control over.
---
	True, but cmd can choose to do a "spawn+wait" or it can choose
to do a "spawn" w/nowait.  The user either sees cmd effectively stopped, or
sees an immediate return.  For example, if I type run "wmined" (under
bash), even though "wmined" can't control whether the parent waits or
not -- it "effectively" does, by "spawning" off a "no-wait copy of itself
and it exits.  The effect or appearance is that "wmined" has controlled
whether or not the shell "waits" by returning a "bogus" exiting process.


Well, two things.  First, the reason you can't just ^Z is because you're
mixing native and Cygwin apps.  If you used a Cygwin gvim (X11) then it
should work just as on *nix.
----
	Well......I just tried a cygwin "find" on /prog for my name,
pressed control-z several times -- it didn't stop until it finished.
(it did respond to control-c, but I had cases where control-c didn't see
to work either -- but those cases may have been winapps).  Certainly,
control-z didn't suspend.


Second, if typing is the issue then: alias gvim='gvim &'
---
	Might not be a bad idea -- though I'd rather hmmmm....
	Well... at the very least, it would be nice to know why gdb
and my baby-redirector both die.  I mean the baby-redirect is pretty
simple...but gdb doesn't even load (but does, of course, under any
cygwin shell...


        Right -- I want the graphical program to launch and return control
to the shell no matter what shell I am in  without having to type &.  "&" is
embedded in my brain as "launch a long running process in background while
I go do something in foreground.  Editing doesn't fit into that paradigm.

Then a wrapper script/wrapper program seems like the correct solution if shell aliases are out.
----
	May not be ... might be best solution ... my 'redirector' can
still exec the gvim in the correct location (without the fork).



        I hesitate to even suggest this, but maybe bash and other shells
should have an option to detect non-cygwin GUI programs and launch them
in background?  It would give a consistent shell presentation on windows
as well as between linux-and-cygwin.  As it stand now, givm launched on
linux launches in background.  gvim launched via cmd.exe or the windows
shell launches in background.  The only place gvim doesn't launch
automatically into the background is under a cygwin shell.

Oh god no. That is going in the opposite direction of consistency with
linux.
----
	I *did* say I was hesitating...:-).

	Let's put the gvim "mostly" on the back burner.  At this point
I'll just ask if you have an idea why 'gdb' won't start.  From a
'completeness' point of view, I'm still wondering why I can't call fork
in a cygwin program from windows.

.. (have been a bit rushed today (and am now, so have to end this)...)
I agree on this, though...

        If cygwin is intended to follow the linux in behavior, I assert,
in this case, it is not and would be more compatible if it new a launched
binary was a Windows-GUI program that would normally be launched in
on windows (or, with its equivalent posix-GUI, on linux).

You're trying to fix the wrong thing. Cygwin is acting exactly as *nix, it's that native gvim that's out of line. On *nix if gvim had the MAY_FORK stuff disabled you'd be in the same exact situation, except that there is no shell on *nix that somehow sniffs binaries to see if they are linked with X11 client libs.
----
Well -- I wasn't trying to fix the wrong thing "initially" -- I was
trying to use cygwin to do the fork and then exec the windows application.
I got hosed because of some weird error that appears to be within the cygwin library that caused the program to die instead of 'fork'....
So don't put me in a corner trying to fix the "wrong" thing. I thought a
wrapper program was a perfect solution (as you seem to suggest as well).
It just didn't work. FYI...here's that intransigent 'C' program:
#include <stdio.h>
#include <errno.h>


extern int errno;

char * const path="/Prog/Vim/gvim.exe";

int main (int argc,char * const argv[]) {
        int p;
        p=fork();
        if (p<0) {
                fprintf(stderr, "Error forking, errno=%d\n",errno);
                exit(1);
        }
        if (!p) {       /* in child */
                execv(path,argv);
                fprintf(stderr, "Error exec'ing %s, errno=%d\n",path,errno);
                exit(2);
        }
        // parent, hopefully, quietly exits....
        exit(0);
}
And here is the path (with some line-breaks after the semi's)
as it is setup in windows (before running any cygwin programs):

C:\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;
C:\Prog\XP-Support Tools;C:\Prog\sysinternals;C:\Prog\Codeplay;
C:\Prog\Common Files\GTK\2.0\bin;C:\Prog\QuickTime\QTSystem\;
C:\bin\Windows;C:\Prog\SecureCRT\;C:\Prog\Microsoft Visual Studio\Tools

Note -- "gdb" was executed with the same path listed above.

-l

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]