At 03:28 PM 10/22/99 +0200, Adrian Aichner wrote:
>>>>> "Craig" == Craig Lanning
<CraigL(a)DyCon.com> writes:
Craig,
I'm confident I found the problem. If so, then it's not related to
95/98 vs. NT.
I'm afraid not :-(
Let me guess that you are NOT building with USE_UNION_TYPE. Well, I
am.
That is correct.
The PID you got below was odd, which is even more evidence.
create_child does a bad thing:
#ifdef USE_UNION_TYPE
cp->pid = (cp->pid & ((1U << VALBITS) - 1));
#else
cp->pid = (cp->pid & VALMASK);
#endif
VALMASK, however, is a shifted mask already. It makes all PIDs even!
lisp-disunion.h:82:#define VALMASK (((1UL << VALBITS) - 1UL) << GCTYPEBITS)
My fix for this is:
cp->pid = XINT(make_int(cp->pid));
Your patch below did not include this line. After I tried the patch and
found that it failed, I was composing my response to your message and
realized that this line wasn't in the patch. So I added it after the line
/* pid must fit in a Lisp_Int */
in ntproc.c. Unfortunately, that did not help :-(
Below I have included the results of the first two test cases.
Please apply following patch and try this extended test case.
Thanks for hanging in there with me!
Thank you for putting up with such a long test cycle.
Adrian
;;;
;;; Test cases
;;;
(call-process "ls" nil '(t t) nil "c:\\")
AUTOEXEC.BAT
<lines deleted by Adrian>
tmp
0
Fatal error: assertion failed, file sysdep.c, line 353, pid != NULL
[then XEmacs died]
(call-process "ls" nil '(t t) nil
"c:\\no-way-you-have-this")
/cygnus/cygwin-b20/H-i586-cygwin32/bin/ls.exe: c:\no-way-you-have-this: No
such file
or directory
1
If you have grep, these would be nice to know:
;;; Looking for drivers in sysem file succeeds, returning 0.
(apply 'call-process "grep" nil nil nil
(list "drivers" "c:\\winnt\\system.ini"))
0
(call-process "grep" nil nil nil "drivers
"c:\\win98\\system.ini")
Fatal error: assertion failed, file sysdep.c, line 353, pid != NULL
[then XEmacs died]
;;; Looking for passangers in sysem file fails, returning 1.
(apply 'call-process "grep" nil nil nil
(list "passangers" "c:\\winnt\\system.ini"))
1
;;; Looking for drivers in invalid file fails, returning 2.
(apply 'call-process "grep" nil nil nil
(list "drivers" "c:\winnt\system.ini"))
2
;;; How about minitar, does IT work?
(call-process "d:\\tmp\\21.2\\xemacs\\nt\\minitar.exe" nil '(t t) nil)
Usage: d:\tmp\21.2\xemacs\nt\minitar.exe file.tar.gz [base-dir]
Extracts the contents compressed tar file to base-dir
-1
Craig> (call-process "ls" nil '(t t) nil "c:\\")
Craig> create_child: exe=c:\BIN32\ls.exe,cmdline=c:\BIN32\ls.exe
Craig> create_child.CreateProcess leads child PID -725391,
Craig> changing to PID 725391 Fatal error: assertion failed, file
Craig> sysdep.c, line 353, pid != NULL
Craig> saw no output and XEmacs locked up.
Craig> Craig
Patch against 21.2-b19:
cd d:\tmp\21.2\xemacs\src\
cvs diff
Compilation started at Fri Oct 22 14:57:00 1999 +0200 (W. Europe Daylight
Time)
? call-process.patch
? call-process.txt
? cvs-diff
? depend-of-make-src-depend
? Installation
? it
? runxemacs.pdb
? sysdep.c.good
? temacs.bsc
? temacs.ilk
? temacs.map
? temacs.pdb
? waitpid.txt
? xemacs.opt
cvs server: Diffing .
Index: callproc.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/callproc.c,v
retrieving revision 1.29.2.6
diff -u -r1.29.2.6 callproc.c
--- callproc.c 1999/05/01 05:13:23 1.29.2.6
+++ callproc.c 1999/10/22 13:05:46
@@ -45,6 +45,7 @@
#define _P_NOWAIT 1 /* from process.h */
#include <windows.h>
#include "nt.h"
+#include "ntheap.h"
#endif
#ifdef DOS_NT
@@ -107,22 +108,33 @@
if (!call_process_exited &&
EMACS_KILLPG (pid, SIGINT) == 0)
- {
- int speccount = specpdl_depth ();
+ {
+ int speccount = specpdl_depth ();
- record_unwind_protect (call_process_kill, fdpid);
- /* #### "c-G" -- need non-consing Single-key-description */
- message ("Waiting for process to die...(type C-g again to kill it
instantly)");
+ record_unwind_protect (call_process_kill, fdpid);
+ /* #### "c-G" -- need non-consing Single-key-description */
+ message ("Waiting for process to die...(type C-g again to kill it
instantly)");
- wait_for_termination (pid);
+#ifdef WINDOWSNT
+ if (os_subtype == OS_WIN95)
+ {
+ wait_for_termination (OpenProcess(PROCESS_ALL_ACCESS, 0, -pid));
+ }
+ else
+ {
+ wait_for_termination (OpenProcess(PROCESS_ALL_ACCESS, 0, pid));
+ }
+#else
+ wait_for_termination (pid);
+#endif
- /* "Discard" the unwind protect. */
- XCAR (fdpid) = Qnil;
- XCDR (fdpid) = Qnil;
- unbind_to (speccount, Qnil);
+ /* "Discard" the unwind protect. */
+ XCAR (fdpid) = Qnil;
+ XCDR (fdpid) = Qnil;
+ unbind_to (speccount, Qnil);
- message ("Waiting for process to die... done");
- }
+ message ("Waiting for process to die... done");
+ }
synch_process_alive = 0;
close (fd);
return Qnil;
@@ -170,6 +182,9 @@
Lisp_Object infile, buffer, current_dir, display, path;
int fd[2];
int filefd;
+#ifdef WINDOWSNT
+ HANDLE pHandle;
+#endif
int pid;
char buf[16384];
char *bufptr = buf;
@@ -358,7 +373,21 @@
fork_error = Qnil;
#ifdef WINDOWSNT
pid = child_setup (filefd, fd1, fd_error, new_argv,
- (char *) XSTRING_DATA (current_dir));
+ (char *) XSTRING_DATA (current_dir));
+ /* OpenProcess() as soon after child_setup as possible. It's too
+ late once the process terminated. */
+ if (os_subtype == OS_WIN95)
+ {
+ stderr_out ("Fcall_process_internal.child_setup returns PID %d, using
PID
%d\n", pid, -pid);
+ /* create_child() in ntproc.c hacks PIDs for OS_WIN95 to fit
+ into Lisp_Int, i.e. negates them. Hence we have to use -pid
+ to get at the real PID for OS_WIN95. */
+ pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, -pid);
+ }
+ else
+ {
+ pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
+ }
#else /* not WINDOWSNT */
pid = fork ();
@@ -435,8 +464,8 @@
#ifdef FILE_CODING
instream =
make_decoding_input_stream
- (XLSTREAM (instream),
- Fget_coding_system (Vcoding_system_for_read));
+ (XLSTREAM (instream),
+ Fget_coding_system (Vcoding_system_for_read));
Lstream_set_character_mode (XLSTREAM (instream));
#endif
NGCPRO1 (instream);
@@ -470,15 +499,16 @@
break;
#ifdef DOS_NT
- /* Until we pull out of MULE things like
- make_decoding_input_stream(), we do the following which is
- less elegant. --marcpa */
- {
- int lf_count = 0;
- if (NILP (Vbinary_process_output)) {
- nread = crlf_to_lf(nread, bufptr, &lf_count);
- }
- }
+ /* Until we pull out of MULE things like
+ make_decoding_input_stream(), we do the following which is
+ less elegant. --marcpa */
+ {
+ int lf_count = 0;
+ if (NILP (Vbinary_process_output))
+ {
+ nread = crlf_to_lf(nread, bufptr, &lf_count);
+ }
+ }
#endif
total_read += nread;
@@ -507,7 +537,11 @@
QUIT;
/* Wait for it to terminate, unless it already has. */
+#ifdef WINDOWSNT
+ wait_for_termination (pHandle);
+#else
wait_for_termination (pid);
+#endif
/* Don't kill any children that the subprocess may have left behind
when exiting. */
Index: ntproc.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/ntproc.c,v
retrieving revision 1.14.2.10
diff -u -r1.14.2.10 ntproc.c
--- ntproc.c 1999/10/10 12:40:13 1.14.2.10
+++ ntproc.c 1999/10/22 13:07:17
@@ -304,14 +304,14 @@
read anything for them to consume yet! */
/*
- if (cp == NULL ||
- WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
+ if (cp == NULL ||
+ WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
*/
if (cp == NULL)
- {
+ {
return 1;
- }
+ }
for (;;)
{
@@ -329,28 +329,31 @@
}
if (rc == STATUS_READ_ERROR)
- {
- /* We are finished, so clean up handles and set to NULL so
- that CHILD_ACTIVE will see what is going on */
- if (cp->char_avail) {
- CloseHandle (cp->char_avail);
- cp->char_avail = NULL;
- }
- if (cp->thrd) {
- CloseHandle (cp->thrd);
- cp->thrd = NULL;
- }
- if (cp->char_consumed) {
- CloseHandle(cp->char_consumed);
- cp->char_consumed = NULL;
- }
- if (cp->procinfo.hProcess)
- {
- CloseHandle (cp->procinfo.hProcess);
- cp->procinfo.hProcess=NULL;
- }
- return 1;
- }
+ {
+ /* We are finished, so clean up handles and set to NULL so
+ that CHILD_ACTIVE will see what is going on */
+ if (cp->char_avail)
+ {
+ CloseHandle (cp->char_avail);
+ cp->char_avail = NULL;
+ }
+ if (cp->thrd)
+ {
+ CloseHandle (cp->thrd);
+ cp->thrd = NULL;
+ }
+ if (cp->char_consumed)
+ {
+ CloseHandle(cp->char_consumed);
+ cp->char_consumed = NULL;
+ }
+ if (cp->procinfo.hProcess)
+ {
+ CloseHandle (cp->procinfo.hProcess);
+ cp->procinfo.hProcess=NULL;
+ }
+ return 1;
+ }
/* If the read died, the child has died so let the thread die */
if (rc == STATUS_READ_FAILED)
@@ -366,23 +369,26 @@
}
/* We are finished, so clean up handles and set to NULL so that
CHILD_ACTIVE will see what is going on */
- if (cp->char_avail) {
- CloseHandle (cp->char_avail);
- cp->char_avail = NULL;
- }
- if (cp->thrd) {
- CloseHandle (cp->thrd);
- cp->thrd = NULL;
- }
- if (cp->char_consumed) {
- CloseHandle(cp->char_consumed);
- cp->char_consumed = NULL;
- }
+ if (cp->char_avail)
+ {
+ CloseHandle (cp->char_avail);
+ cp->char_avail = NULL;
+ }
+ if (cp->thrd)
+ {
+ CloseHandle (cp->thrd);
+ cp->thrd = NULL;
+ }
+ if (cp->char_consumed)
+ {
+ CloseHandle(cp->char_consumed);
+ cp->char_consumed = NULL;
+ }
if (cp->procinfo.hProcess)
- {
- CloseHandle (cp->procinfo.hProcess);
- cp->procinfo.hProcess=NULL;
- }
+ {
+ CloseHandle (cp->procinfo.hProcess);
+ cp->procinfo.hProcess=NULL;
+ }
return 0;
}
@@ -448,16 +454,15 @@
/* Hack for Windows 95, which assigns large (ie negative) pids */
if (cp->pid < 0)
cp->pid = -cp->pid;
-
/* pid must fit in a Lisp_Int */
-#ifdef USE_UNION_TYPE
- cp->pid = (cp->pid & ((1U << VALBITS) - 1));
-#else
- cp->pid = (cp->pid & VALMASK);
-#endif
+
+ if (cp->pid > EMACS_INT_MAX) {
+ stderr_out ("create_child.CreateProcess abs(PID) %d > EMACS_INT_MAX
(%d)\n",
+ cp->pid, EMACS_INT_MAX);
+ }
*pPid = cp->pid;
-
+
return TRUE;
EH_Fail:
Index: sysdep.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/sysdep.c,v
retrieving revision 1.32.2.7
diff -u -r1.32.2.7 sysdep.c
--- sysdep.c 1999/07/05 05:56:44 1.32.2.7
+++ sysdep.c 1999/10/22 13:08:31
@@ -234,8 +234,11 @@
#endif /* NO_SUBPROCESSES */
-void
-wait_for_termination (int pid)
+#ifdef WINDOWSNT
+void wait_for_termination (HANDLE pid)
+#else
+void wait_for_termination (int pid)
+#endif
{
/* #### With the new improved SIGCHLD handling stuff, there is much
less danger of race conditions and some of the comments below
@@ -345,6 +348,43 @@
Since implementations may add their own error indicators on top,
we ignore it by default. */
+#elif defined (WINDOWSNT)
+ int ret = 0, status = 0;
+ assert (pid != NULL);
+ do
+ {
+ QUIT;
+ ret = WaitForSingleObject(pid, 100);
+ }
+ while (ret == WAIT_TIMEOUT);
+ if (ret == WAIT_FAILED)
+ {
+ stderr_out ("wait_for_termination.WaitForSingleObject returns %d
(WAIT_FAILED) GetLastError () %d for pid %d\n", ret, GetLastError (),
(int)pid);
+ }
+ if (ret == WAIT_ABANDONED)
+ {
+ stderr_out ("wait_for_termination.WaitForSingleObject returns %d
(WAIT_ABANDONED) GetLastError () %d for pid %d\n", ret, GetLastError (),
(int)pid);
+ }
+ if (ret == WAIT_OBJECT_0)
+ {
+ ret = GetExitCodeProcess(pid, &status);
+ if (ret)
+ {
+ synch_process_alive = 0;
+ synch_process_retcode = status;
+ }
+ else
+ {
+ /* GetExitCodeProcess() didn't return a valid exit status,
+ nothing to do. APA */
+ stderr_out ("wait_for_termination.GetExitCodeProcess status %d
GetLastError
() %d for pid %d\n", status, GetLastError (), (int)pid);
+ }
+ }
+ if (!CloseHandle(pid))
+ {
+ stderr_out ("wait_for_termination.CloseHandle GetLastError () %d
for pid
%d\n",
+ GetLastError (), (int)pid);
+ }
#elif defined (EMACS_BLOCK_SIGNAL) && !defined (BROKEN_WAIT_FOR_SIGNAL)
&& defined (SIGCHLD)
while (1)
{
@@ -376,7 +416,7 @@
Try defining BROKEN_WAIT_FOR_SIGNAL. */
EMACS_WAIT_FOR_SIGNAL (SIGCHLD);
}
-#else /* not HAVE_WAITPID and (not EMACS_BLOCK_SIGNAL or
BROKEN_WAIT_FOR_SIGNAL)
*/
+#else /* not HAVE_WAITPID and not WINDOWSNT and (not
EMACS_BLOCK_SIGNAL
or BROKEN_WAIT_FOR_SIGNAL) */
/* This approach is kind of cheesy but is guaranteed(?!) to work
for all systems. */
while (1)
@@ -578,7 +618,11 @@
static void
sys_subshell (void)
{
+#ifdef WINDOWSNT
+ HANDLE pid;
+#else
int pid;
+#endif
struct save_signal saved_handlers[5];
Lisp_Object dir;
unsigned char *str = 0;
@@ -617,7 +661,7 @@
xyzzy:
#ifdef WINDOWSNT
- pid = -1;
+ pid = NULL;
#else /* not WINDOWSNT */
pid = fork ();
@@ -651,7 +695,7 @@
#ifdef WINDOWSNT
/* Waits for process completion */
pid = _spawnlp (_P_WAIT, sh, sh, NULL);
- if (pid == -1)
+ if (pid == NULL)
write (1, "Can't execute subshell", 22);
#else /* not WINDOWSNT */
Index: sysdep.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/sysdep.h,v
retrieving revision 1.11.2.1
diff -u -r1.11.2.1 sysdep.h
--- sysdep.h 1998/12/05 16:56:31 1.11.2.1
+++ sysdep.h 1999/10/22 13:08:38
@@ -48,7 +48,12 @@
/* Wait for subprocess with process id `pid' to terminate and
make sure it will get eliminated (not remain forever as a zombie) */
+#ifdef WINDOWSNT
+#include <windows.h>
+void wait_for_termination (HANDLE pid);
+#else
void wait_for_termination (int pid);
+#endif
/* flush any pending output
* (may flush input as well; it does not matter the way we use it)
cvs server: Diffing m
cvs server: Diffing s
Compilation exited abnormally with code 1 at Fri Oct 22 15:00:31