>>>> "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.
Craig> I'm afraid not :-(
Hi Craig,
I'm so far past my wit's end, that I'm getting serious again!
I have revisited my options and settled for minimal change. This is
the realistic route to get this into 21.1.8 (no, I havn't given up
just yet, I hope you haven't either).
This patch is against 21.2-b19 again, but it's smaller. I have
reverted all my indentation changes (which make the functions I
touched comply with GNU formatting standards).
Reviewing each patch hunk I have re-implemented the whole thing.
I invert 95/98 PIDs in create_child and keep them that way when
converting to Lisp_Int. Everywhere Lisp_Int PIDs are converted back
to int, I invert them (when on OS_WIN95) before use. Wherever I call
OpenProcess I invert the PID for OS_WIN95.
I have proven my patch to be correct by inverting all tests from
if (os_subtype == OS_WIN95)
to
if (os_subtype != OS_WIN95)
Now I get these warnings on NT:
Fcall_process_internal.child_setup returns PID -306, using PID 306
create_child.CreateProcess abs(PID) -343 > EMACS_INT_MAX (2147483647)
Fcall_process_internal.child_setup returns PID -343, using PID 343
create_child.CreateProcess abs(PID) -282 > EMACS_INT_MAX (2147483647)
Fcall_process_internal.child_setup returns PID -282, using PID 282
create_child.CreateProcess abs(PID) -280 > EMACS_INT_MAX (2147483647)
Fcall_process_internal.child_setup returns PID -280, using PID 280
create_child.CreateProcess abs(PID) -146 > EMACS_INT_MAX (2147483647)
Fcall_process_internal.child_setup returns PID -146, using PID 146
create_child.CreateProcess abs(PID) -298 > EMACS_INT_MAX (2147483647)
Fcall_process_internal.child_setup returns PID -298, using PID 298
BUT, call-process still works, returning correct exit status and never
obtaining invalid process handles. This proves that negative PIDs can
be passed to Lisp and back. On Windows 95/98 we will need the
opposite, but that requires one bit less.
I had to disable a meaningless fork test in src/callproc.c for
WINDOWSNT, which I intend to leave in:
#ifndef WINDOWSNT
if (pid < 0)
{
if (fd[0] >= 0)
close (fd[0]);
report_file_error ("Doing fork", Qnil);
}
#endif
Please try this patch and, by all means, report success!
Are there any more testers on 95/98 out there? Testing with and
without USE_UNION_TYPE is desirable.
Please refer to earlier test-cases in this thread and send me their
output, as well as any STDERR of XEmacs itself.
Thanks in advance!
Adrian
> Let me guess that you are NOT building with USE_UNION_TYPE.
> Well, I am.
Craig> That is correct.
Patch against 21.2-b19 (to be applied in xemacs/src):
cd d:\tmp\21.2\xemacs\src\
cvs diff
Compilation started at Sat Oct 23 17:42:11 1999 +0200 (W. Europe Daylight Time)
? call-process-notes
? 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/23 15:51:17
@@ -45,6 +45,7 @@
#define _P_NOWAIT 1 /* from process.h */
#include <windows.h>
#include "nt.h"
+#include "ntheap.h"
#endif
#ifdef DOS_NT
@@ -86,14 +87,22 @@
static Lisp_Object
call_process_kill (Lisp_Object fdpid)
{
- Lisp_Object fd = Fcar (fdpid);
- Lisp_Object pid = Fcdr (fdpid);
+ Lisp_Object lfd = Fcar (fdpid);
+ Lisp_Object lpid = Fcdr (fdpid);
+ int fd = XINT (lfd);
+ int pid = XINT (lpid);
- if (!NILP (fd))
- close (XINT (fd));
+#ifdef WINDOWSNT
+ if (os_subtype == OS_WIN95)
+ {
+ pid = -pid;
+ }
+#endif
+ if (!NILP (lfd))
+ close (fd);
- if (!NILP (pid))
- EMACS_KILLPG (XINT (pid), SIGKILL);
+ if (!NILP (lpid))
+ EMACS_KILLPG (pid, SIGKILL);
synch_process_alive = 0;
return Qnil;
@@ -105,6 +114,12 @@
int fd = XINT (Fcar (fdpid));
int pid = XINT (Fcdr (fdpid));
+#ifdef WINDOWSNT
+ if (os_subtype == OS_WIN95)
+ {
+ pid = -pid;
+ }
+#endif
if (!call_process_exited &&
EMACS_KILLPG (pid, SIGINT) == 0)
{
@@ -114,7 +129,11 @@
/* #### "c-G" -- need non-consing Single-key-description */
message ("Waiting for process to die...(type C-g again to kill it
instantly)");
+#ifdef WINDOWSNT
+ wait_for_termination (OpenProcess(PROCESS_ALL_ACCESS, 0, pid));
+#else
wait_for_termination (pid);
+#endif
/* "Discard" the unwind protect. */
XCAR (fdpid) = Qnil;
@@ -170,6 +189,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;
@@ -359,6 +381,20 @@
#ifdef WINDOWSNT
pid = child_setup (filefd, fd1, fd_error, new_argv,
(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 ();
@@ -394,12 +430,14 @@
if (!NILP (fork_error))
signal_error (Qfile_error, fork_error);
+#ifndef WINDOWSNT
if (pid < 0)
{
if (fd[0] >= 0)
close (fd[0]);
report_file_error ("Doing fork", Qnil);
}
+#endif
if (INTP (buffer))
{
@@ -507,7 +545,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/23 15:51:28
@@ -446,15 +446,19 @@
cp->procinfo.hProcess=NULL;
/* Hack for Windows 95, which assigns large (ie negative) pids */
- if (cp->pid < 0)
- cp->pid = -cp->pid;
+#ifdef WINDOWSNT
+ if (os_subtype == OS_WIN95)
+ {
+ cp->pid = -cp->pid;
+ }
+#endif
/* 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;
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/23 15:51:45
@@ -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,47 @@
Since implementations may add their own error indicators on top,
we ignore it by default. */
+#elif defined (WINDOWSNT)
+ int ret = 0, status = 0;
+ if (pid == NULL)
+ {
+ stderr_out ("wait_for_termination: pid == NULL, GetLastError () = %d, (int)pid
= %d\n", GetLastError (), (int)pid);
+ return;
+ }
+ 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 +420,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 +622,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 +665,7 @@
xyzzy:
#ifdef WINDOWSNT
- pid = -1;
+ pid = NULL;
#else /* not WINDOWSNT */
pid = fork ();
@@ -651,7 +699,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/23 15:51:46
@@ -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 Sat Oct 23 17:43:17