Could the experts in these areas please comment on this patch of mine?
I will add a ChangeLog after I resolve any remaining issues.
Please see
http://www.xemacs.org/list-archives/xemacs-beta/9911/msg00193.html for
my assessment of the fstat/stat problems on Windows NT. I'd like to
hear from you if I've drawn any wrong conclusions.
Changes to
src/callproc.c
src/ntproc.c
src/sysdep.c
and
src/sysdep.h
implement the call-process patch which is in 21.1.8 already.
However, following Ben's request, I have replaced stderr_out () with
warn_when_safe ().
The part I am concerned about is my ENCAPSULATION for fstat, which is
required on Windows NT to avoid inconsistencies between the already
encapsulated stat system call and the broken fstat on NT. Do I need
to qualify it somehow, so that it only affects native Windows NT
builds? I didn't understand how stat is only encapsualted on NT
native.
The files changed are:
src/nt.c
src/sysdep.c
src/sysfile.h
Please advise about any shortcomings of this patch and directions for
possible fixes.
Many thanks!
Adrian
I have verified a patched XEmacs to report consistent file times
cd d:\tmp\21.2\xemacs\
cvs diff
Compilation started at Wed Nov 10 03:09:36 1999 +0100 (W. Europe Standard Time)
Index: src/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/11/10 02:13:47
@@ -104,6 +104,9 @@
{
int fd = XINT (Fcar (fdpid));
int pid = XINT (Fcdr (fdpid));
+#ifdef WINDOWSNT
+ HANDLE pHandle;
+#endif
if (!call_process_exited &&
EMACS_KILLPG (pid, SIGINT) == 0)
@@ -114,7 +117,17 @@
/* #### "c-G" -- need non-consing Single-key-description */
message ("Waiting for process to die...(type C-g again to kill it
instantly)");
+#ifdef WINDOWSNT
+ pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
+ if (pHandle == NULL)
+ {
+ warn_when_safe (Qprocess, Qerror,
+ "OpenProcess returns NULL process handle.");
+ }
+ wait_for_termination (pHandle);
+#else
wait_for_termination (pid);
+#endif
/* "Discard" the unwind protect. */
XCAR (fdpid) = Qnil;
@@ -170,6 +183,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 +375,20 @@
#ifdef WINDOWSNT
pid = child_setup (filefd, fd1, fd_error, new_argv,
(char *) XSTRING_DATA (current_dir));
+ if (!INTP (buffer))
+ {
+ /* OpenProcess() as soon after child_setup as possible. It's too
+ late once the process terminated. */
+ pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
+ if (pHandle == NULL)
+ {
+ warn_when_safe (Qprocess, Qerror,
+ "OpenProcess returns NULL process handle.");
+ }
+ }
+ /* Close STDERR into the parent process. We no longer need it. */
+ if (fd_error >= 0)
+ close (fd_error);
#else /* not WINDOWSNT */
pid = fork ();
@@ -394,12 +424,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 +539,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: src/nt.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/nt.c,v
retrieving revision 1.17.2.4
diff -u -r1.17.2.4 nt.c
--- nt.c 1999/07/05 05:56:43 1.17.2.4
+++ nt.c 1999/11/10 02:14:24
@@ -1313,6 +1313,40 @@
#endif
+/* Since stat is encapsulated on Windows NT, we need to encapsulate
+ the equally broken fstat as well. */
+int
+fstat (int handle, struct stat *buffer)
+{
+ int ret;
+ BY_HANDLE_FILE_INFORMATION lpFileInfo;
+ /* Initialize values */
+ buffer->st_mode = 0;
+ buffer->st_size = 0;
+ buffer->st_dev = 0;
+ buffer->st_rdev = 0;
+ buffer->st_atime = 0;
+ buffer->st_ctime = 0;
+ buffer->st_mtime = 0;
+ buffer->st_nlink = 0;
+ ret = GetFileInformationByHandle((HANDLE) handle, &lpFileInfo);
+ if (!ret)
+ {
+ return -1;
+ }
+ else
+ {
+ buffer->st_mtime = convert_time (lpFileInfo.ftLastWriteTime);
+ buffer->st_atime = convert_time (lpFileInfo.ftLastAccessTime);
+ if (buffer->st_atime == 0) buffer->st_atime = buffer->st_mtime;
+ buffer->st_ctime = convert_time (lpFileInfo.ftCreationTime);
+ if (buffer->st_ctime == 0) buffer->st_ctime = buffer->st_mtime;
+ buffer->st_size = lpFileInfo.nFileSizeLow;
+ buffer->st_nlink = (short) lpFileInfo.nNumberOfLinks;
+ return 0;
+ }
+}
+
/* MSVC stat function can't cope with UNC names and has other bugs, so
replace it with our own. This also allows us to calculate consistent
inode values without hacks in the main Emacs code. */
Index: src/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/11/10 02:14:30
@@ -445,16 +445,8 @@
cp->procinfo.hThread=NULL;
cp->procinfo.hProcess=NULL;
- /* 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
+
*pPid = cp->pid;
Index: src/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/11/10 02:14:44
@@ -234,8 +234,11 @@
#endif /* NO_SUBPROCESSES */
-void
-wait_for_termination (int pid)
+#ifdef WINDOWSNT
+void wait_for_termination (HANDLE pHandle)
+#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,53 @@
Since implementations may add their own error indicators on top,
we ignore it by default. */
+#elif defined (WINDOWSNT)
+ int ret = 0, status = 0;
+ if (pHandle == NULL)
+ {
+ warn_when_safe (Qprocess, Qerror, "Cannot wait for NULL process
handle.");
+ return;
+ }
+ do
+ {
+ QUIT;
+ ret = WaitForSingleObject(pHandle, 100);
+ }
+ while (ret == WAIT_TIMEOUT);
+ if (ret == WAIT_FAILED)
+ {
+ warn_when_safe (Qprocess, Qerror,
+ "WaitForSingleObject returns WAIT_FAILED for process handle %p.",
+ pHandle);
+ }
+ if (ret == WAIT_ABANDONED)
+ {
+ warn_when_safe (Qprocess, Qerror,
+ "WaitForSingleObject returns WAIT_ABANDONED for process handle %p.",
+ pHandle);
+ }
+ if (ret == WAIT_OBJECT_0)
+ {
+ ret = GetExitCodeProcess(pHandle, &status);
+ if (ret)
+ {
+ synch_process_alive = 0;
+ synch_process_retcode = status;
+ }
+ else
+ {
+ /* GetExitCodeProcess() didn't return a valid exit status,
+ nothing to do. APA */
+ warn_when_safe (Qprocess, Qerror,
+ "GetExitCodeProcess fails for process handle %p.",
+ pHandle);
+ }
+ }
+ if (pHandle != NULL && !CloseHandle(pHandle))
+ {
+ warn_when_safe (Qprocess, Qerror,
+ "CloseHandle fails for process handle %p.", pHandle);
+ }
#elif defined (EMACS_BLOCK_SIGNAL) && !defined (BROKEN_WAIT_FOR_SIGNAL)
&& defined (SIGCHLD)
while (1)
{
@@ -376,7 +426,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 +628,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 +671,7 @@
xyzzy:
#ifdef WINDOWSNT
- pid = -1;
+ pid = NULL;
#else /* not WINDOWSNT */
pid = fork ();
@@ -651,7 +705,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 */
@@ -3036,6 +3090,15 @@
return readlink (path, buf, bufsiz);
}
#endif /* ENCAPSULATE_READLINK */
+
+
+#ifdef ENCAPSULATE_FSTAT
+int
+sys_fstat (int fd, struct stat *buf)
+{
+ return fstat (fd, buf);
+}
+#endif /* ENCAPSULATE_FSTAT */
#ifdef ENCAPSULATE_STAT
Index: src/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/11/10 02:14:45
@@ -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)
Index: src/sysfile.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/sysfile.h,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 sysfile.h
--- sysfile.h 1998/12/05 16:56:32 1.7.2.1
+++ sysfile.h 1999/11/10 02:14:46
@@ -380,6 +380,18 @@
# define sys_readlink readlink
#endif
+#ifdef ENCAPSULATE_FSTAT
+int sys_fstat (int fd, struct stat *buf);
+#endif
+#if defined (ENCAPSULATE_FSTAT) && !defined (DONT_ENCAPSULATE)
+# undef fstat
+/* Need to use arguments to avoid messing with struct stat */
+# define fstat(fd, buf) sys_fstat (fd, buf)
+#endif
+#if !defined (ENCAPSULATE_FSTAT) && defined (DONT_ENCAPSULATE)
+# define sys_fstat fstat
+#endif
+
#ifdef ENCAPSULATE_STAT
int sys_stat (CONST char *path, struct stat *buf);
#endif
cvs server: Diffing src/m
cvs server: Diffing src/s
cvs server: Diffing tests
cvs server: Diffing tests/DLL
cvs server: Diffing tests/Dnd
cvs server: Diffing tests/automated
cvs server: Diffing tests/mule
cvs server: Diffing tests/tooltalk
Compilation exited abnormally with code 1 at Wed Nov 10 03:14:21