>>>> "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.
Let me guess that you are NOT building with USE_UNION_TYPE. Well, I am.
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));
Please apply following patch and try this extended test case.
Thanks for hanging in there with me!
Adrian
;;;
;;; Test cases
;;;
(call-process "ls" nil '(t t) nil "c:\\")
AUTOEXEC.BAT
<lines deleted by Adrian>
tmp
0
(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
;;; 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