Subject: subprocess i/o interaction with shell (bash&cmd): shells compete for input with user program!
From: Sam Steingold <[email-masked]>
To: [email-masked]
Cc: [email-masked]
Date: 22 Jul 2003 10:30:52 -0400

I have a driver.exe program which calls runtime.exe.
runtime.exe is an interactive console application, i.e.,
it will be doing i/o via the stdio.
If I make driver.exe exit before runtime.exe, the console interaction
is severely broken (both under bash and cmd, both when compiled with and
without cygwin)

E.g.:
=================== start driver.c ==============================
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <windows.h>

int main (int argc, char *argv[]) {
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
  si.cb = sizeof(STARTUPINFO);
  si.lpReserved = NULL;
  si.lpDesktop = NULL;
  si.lpTitle = NULL;
  si.cbReserved2 = 0;
  si.lpReserved2 = NULL;
  si.dwFlags = STARTF_USESTDHANDLES;
  si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
  if (si.hStdInput == INVALID_HANDLE_VALUE)  goto w32err;
  si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  if (si.hStdOutput == INVALID_HANDLE_VALUE) goto w32err;
  si.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
  if (si.hStdError == INVALID_HANDLE_VALUE)  goto w32err;
  printf(" * start (%d) %s\n",argc,argv[0]);
  if (!CreateProcess("runtime.exe","runtime.exe",NULL,NULL,1,0,
                     NULL,NULL,&si,&pi))
    goto w32err;
  if (argc>1)
    WaitForSingleObject(pi.hProcess,INFINITE);
  printf(" * finish %s\n",argv[0]);
  return 0;
 w32err:
  fprintf(stderr," * error %s: %s\n",argv[0],strerror(GetLastError()));
  return 1;
}
=================== end driver.c ==============================
=================== start runtime.c ==============================
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
  char buf[BUFSIZ];
  printf(" * start (%d) %s\n",argc,argv[0]);
  gets(buf);
  printf(" * you entered: [%s]\n",buf);
  printf(" * finish %s\n",argv[0]);
  return 0;
}
=================== end runtime.c ==============================

I compile them with
gcc -mno-cygwin -g -W -Wall -Wstrict-prototypes -Wshadow driver.c -o driver
gcc -mno-cygwin -g -W -Wall -Wstrict-prototypes -Wshadow runtime.c -o runtime

When I give the driver an argument so that it will wait for runtime to
finish, I get what one would expect, both under bash and cmd:

================================ start bash interaction ===========
bash$ ./driver.exe wait
 * start (2) d:\sds\c\driver.exe
 * start (1) runtime.exe
qwert
 * you entered: [qwert]
 * finish runtime.exe
 * finish d:\sds\c\driver.exe
bash$
================================ end bash interaction ===========

================================ start cmd interaction ===========
D:\sds\c>driver wait
 * start (2) driver
 * start (1) runtime.exe
qwert
 * you entered: [qwert]
 * finish runtime.exe
 * finish driver

D:\sds\c>
================================ end cmd interaction ===========

now, if I do not give the `wait' argument to the driver, I get
something quite unexpected under cmd:

================================ start cmd interaction ===========
D:\sds\c>driver
 * start (1) driver
 * finish driver

D:\sds\c> * start (1) runtime.exe
qwer
'qwer' is not recognized as an internal or external command,
operable program or batch file.

D:\sds\c>asdf
 * you entered: [asdf]
 * finish runtime.exe
================================ end cmd interaction ===========

i.e., I get the cmd prompt right after driver exits and the first thing
I input is caught by cmd (and the second line goes to runtime).

================================ start bash interaction ===========
bash$ ./driver.exe
 * start (1) d:\sds\c\driver.exe
 * finish d:\sds\c\driver.exe
bash$  * start (1) runtime.exe
defxctutirfefe
bash: defxctutirfefe: command not found
bash$ 3sssssd
bash: 3sssssd: command not found
bash$
bash$ p4khdsf
bash: p4khdsf: command not found
bash$ ^C
bash$
================================ end bash interaction ===========

i.e., I get the bash prompt right after driver exits, BUT the input
becomes weird: only about a quarter of the characters I type are echoed
to the screen (the `3sssssd' string was generated by me repeatedly
typing "asdasdfasdfadfasdfadsf") and the only way out is Ctrl-C (then
everything is restored to normal, but I never see the finishing messages
from runtime.exe).

Ironically, if I compile them with cygwin:
gcc -g -W -Wall -Wstrict-prototypes -Wshadow driver.c -o driver
gcc -g -W -Wall -Wstrict-prototypes -Wshadow runtime.c -o runtime

the results are identical on bash and cmd and somewhat in between the
mingw behavior (i.e., bash is better and cmd is worse):

================================ start bash interaction ===========
bash$ ./driver.exe
 * start (1) ./driver
 * finish ./driver
bash$  * start (1) runtime
sfgggdfrg
bash: sfggdrg: command not found
bash$ rwr
bash: rwr: command not found
bash$
bash$
bash$
bash$
bash$
bash$
bash$
bash$
bash$
bash$
bash$ 54
bash: 5: command not found
bash$ 5676
 * you entered: [gf4676]
 * finish runtime

bash: 5: command not found
bash$
bash$
================================ end bash interaction ===========

================================ start cmd interaction ===========
D:\sds\c>driver
 * start (1) driver
 * finish driver

D:\sds\c> * start (1) runtime
qdf
'qdf' is not recognized as an internal or external command,
operable program or batch file.

D:\sds\c>er
'r' is not recognized as an internal or external command,
operable program or batch file.

D:\sds\c>qerq4
'erq4' is not recognized as an internal or external command,
operable program or batch file.

D:\sds\c>
 * you entered: [eq]
 * finish runtime

D:\sds\c>
D:\sds\c>
================================ end cmd interaction ===========

i.e., as you can see, the shells compete with runtime for input!

using cygwin exec() family does not change much (I still get the
bash/cmd prompt before runtime starts).

So, how can I exit driver and have the shell notice that its child
(driver) left a heir (runtime) and that the shell (bash & cmd) should
wait for runtime to finish.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
The difference between theory and practice is that in theory there isn't any.

--
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/