aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-12-15 15:38:21 +0200
committerEli Zaretskii2012-12-15 15:38:21 +0200
commitb07286179ec721bc44a7e32111318fb325789fe1 (patch)
tree605b9464822cc82d4b9b2e437c6711622142c7d5 /src
parent279f9b06fd693b67d1178cdb5ad1ecf513d199ad (diff)
downloademacs-b07286179ec721bc44a7e32111318fb325789fe1.tar.gz
emacs-b07286179ec721bc44a7e32111318fb325789fe1.zip
Fix bug #13079 on MS-Windows with temp files not being deleted.
src/w32.h (_child_process): New members input_file and pending_deletion. (register_child): First argument is now pid_t. (record_infile, record_pending_deletion): New prototypes. src/w32proc.c (new_child): Initialize input_file and pending_deletion members of the child. (delete_child): Delete the child's temporary input file, if any, that is pending deletion. (register_child): First argument is now pid_t. (record_infile, record_pending_deletion): New functions. (reap_subprocess): Fix a typo in DebPrint string. (sys_spawnve, sys_kill): Use pid_t for PID arguments. src/fileio.c (internal_delete_file): Return an int again: non-zero if delete-file succeeds, zero otherwise. src/lisp.h (internal_delete_file): Adjust prototype. src/callproc.c (Fcall_process): Don't overwrite infile with result of DECODE_FILE. [WINDOWSNT] If BUFFER is an integer, i.e. we are launching an asynchronous subprocess, record the name of the input file name, if any. (delete_temp_file) [WINDOWSNT]: If internal_delete_file fails to delete the file, record it as pending deletion when the subprocess exits. nt/inc/ms-w32.h (sys_unlink): Provide prototype.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog31
-rw-r--r--src/callproc.c29
-rw-r--r--src/fileio.c11
-rw-r--r--src/lisp.h2
-rw-r--r--src/w32.h10
-rw-r--r--src/w32proc.c66
6 files changed, 134 insertions, 15 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 960e4e52c59..34959cb691d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,34 @@
12012-12-15 Eli Zaretskii <eliz@gnu.org>
2
3 Fix bug #13079 on MS-Windows with temp files not being deleted.
4 * w32.h (_child_process): New members input_file and
5 pending_deletion.
6 (register_child): First argument is now pid_t.
7 (record_infile, record_pending_deletion): New prototypes.
8
9 * w32proc.c (new_child): Initialize input_file and
10 pending_deletion members of the child.
11 (delete_child): Delete the child's temporary input file, if any,
12 that is pending deletion.
13 (register_child): First argument is now pid_t.
14 (record_infile, record_pending_deletion): New functions.
15 (reap_subprocess): Fix a typo in DebPrint string.
16 (sys_spawnve, sys_kill): Use pid_t for PID arguments.
17
18 * fileio.c (internal_delete_file): Return an int again: non-zero
19 if delete-file succeeds, zero otherwise.
20
21 * lisp.h (internal_delete_file): Adjust prototype.
22
23 * callproc.c (Fcall_process): Don't overwrite infile with result
24 of DECODE_FILE.
25 [WINDOWSNT] If BUFFER is an integer, i.e. we are launching an
26 asynchronous subprocess, record the name of the input file name,
27 if any.
28 (delete_temp_file) [WINDOWSNT]: If internal_delete_file fails to
29 delete the file, record it as pending deletion when the subprocess
30 exits.
31
12012-12-14 Eli Zaretskii <eliz@gnu.org> 322012-12-14 Eli Zaretskii <eliz@gnu.org>
2 33
3 * editfns.c [HAVE_PWD_H]: Include grp.h. 34 * editfns.c [HAVE_PWD_H]: Include grp.h.
diff --git a/src/callproc.c b/src/callproc.c
index e064dccd6d3..5eba3271358 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -402,10 +402,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
402 402
403 filefd = emacs_open (SSDATA (infile), O_RDONLY, 0); 403 filefd = emacs_open (SSDATA (infile), O_RDONLY, 0);
404 if (filefd < 0) 404 if (filefd < 0)
405 { 405 report_file_error ("Opening process input file",
406 infile = DECODE_FILE (infile); 406 Fcons (DECODE_FILE (infile), Qnil));
407 report_file_error ("Opening process input file", Fcons (infile, Qnil));
408 }
409 407
410 if (STRINGP (output_file)) 408 if (STRINGP (output_file))
411 { 409 {
@@ -612,6 +610,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
612 610
613#ifdef WINDOWSNT 611#ifdef WINDOWSNT
614 pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir); 612 pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
613 /* We need to record the input file of this child, for when we are
614 called from call-process-region to create an async subprocess.
615 That's because call-process-region's unwind procedure will
616 attempt to delete the temporary input file, which will fail
617 because that file is still in use. Recording it with the child
618 will allow us to delete the file when the subprocess exits.
619 The second part of this is in delete_temp_file, q.v. */
620 if (pid > 0 && INTEGERP (buffer) && nargs >= 2 && !NILP (args[1]))
621 record_infile (pid, xstrdup (SSDATA (infile)));
615#else /* not WINDOWSNT */ 622#else /* not WINDOWSNT */
616 623
617 /* vfork, and prevent local vars from being clobbered by the vfork. */ 624 /* vfork, and prevent local vars from being clobbered by the vfork. */
@@ -924,7 +931,21 @@ delete_temp_file (Lisp_Object name)
924 /* Suppress jka-compr handling, etc. */ 931 /* Suppress jka-compr handling, etc. */
925 ptrdiff_t count = SPECPDL_INDEX (); 932 ptrdiff_t count = SPECPDL_INDEX ();
926 specbind (intern ("file-name-handler-alist"), Qnil); 933 specbind (intern ("file-name-handler-alist"), Qnil);
934#ifdef WINDOWSNT
935 /* If this is called when the subprocess didn't exit yet, the
936 attempt to delete its input file will fail. In that case, we
937 schedule the file for deletion when the subprocess exits. This
938 is the 2nd part of handling this situation; see the call to
939 record_infile in call-process above, for the first part. */
940 if (!internal_delete_file (name))
941 {
942 Lisp_Object encoded_file = ENCODE_FILE (name);
943
944 record_pending_deletion (SSDATA (encoded_file));
945 }
946#else
927 internal_delete_file (name); 947 internal_delete_file (name);
948#endif
928 unbind_to (count, Qnil); 949 unbind_to (count, Qnil);
929 return Qnil; 950 return Qnil;
930} 951}
diff --git a/src/fileio.c b/src/fileio.c
index c7df87bcdda..9f263e36943 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2203,14 +2203,17 @@ internal_delete_file_1 (Lisp_Object ignore)
2203 return Qt; 2203 return Qt;
2204} 2204}
2205 2205
2206/* Delete file FILENAME. 2206/* Delete file FILENAME, returning 1 if successful and 0 if failed.
2207 This ignores `delete-by-moving-to-trash'. */ 2207 This ignores `delete-by-moving-to-trash'. */
2208 2208
2209void 2209int
2210internal_delete_file (Lisp_Object filename) 2210internal_delete_file (Lisp_Object filename)
2211{ 2211{
2212 internal_condition_case_2 (Fdelete_file, filename, Qnil, 2212 Lisp_Object tem;
2213 Qt, internal_delete_file_1); 2213
2214 tem = internal_condition_case_2 (Fdelete_file, filename, Qnil,
2215 Qt, internal_delete_file_1);
2216 return NILP (tem);
2214} 2217}
2215 2218
2216DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, 2219DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
diff --git a/src/lisp.h b/src/lisp.h
index c7a70feced7..84a97c17bba 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3199,7 +3199,7 @@ EXFUN (Fread_file_name, 6); /* Not a normal DEFUN. */
3199extern Lisp_Object close_file_unwind (Lisp_Object); 3199extern Lisp_Object close_file_unwind (Lisp_Object);
3200extern Lisp_Object restore_point_unwind (Lisp_Object); 3200extern Lisp_Object restore_point_unwind (Lisp_Object);
3201extern _Noreturn void report_file_error (const char *, Lisp_Object); 3201extern _Noreturn void report_file_error (const char *, Lisp_Object);
3202extern void internal_delete_file (Lisp_Object); 3202extern int internal_delete_file (Lisp_Object);
3203extern bool file_directory_p (const char *); 3203extern bool file_directory_p (const char *);
3204extern bool file_accessible_directory_p (const char *); 3204extern bool file_accessible_directory_p (const char *);
3205extern void syms_of_fileio (void); 3205extern void syms_of_fileio (void);
diff --git a/src/w32.h b/src/w32.h
index 86f9c992fe8..a43a5133eb4 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -103,6 +103,12 @@ typedef struct _child_process
103 OVERLAPPED ovl_read; 103 OVERLAPPED ovl_read;
104 /* Used for async write operations on serial comm ports. */ 104 /* Used for async write operations on serial comm ports. */
105 OVERLAPPED ovl_write; 105 OVERLAPPED ovl_write;
106 /* Input file, if any, for this subprocess. Should only be non-NULL
107 for async subprocesses. */
108 char *input_file;
109 /* If non-zero, the subprocess input file is temporary and should be
110 deleted when the subprocess exits. */
111 int pending_deletion;
106} child_process; 112} child_process;
107 113
108#define MAXDESC FD_SETSIZE 114#define MAXDESC FD_SETSIZE
@@ -184,7 +190,9 @@ extern int sys_pipe (int *);
184 190
185extern void set_process_dir (char *); 191extern void set_process_dir (char *);
186extern int sys_spawnve (int, char *, char **, char **); 192extern int sys_spawnve (int, char *, char **, char **);
187extern void register_child (int, int); 193extern void register_child (pid_t, int);
194extern void record_infile (pid_t, char *);
195extern void record_pending_deletion (char *);
188 196
189extern void sys_sleep (int); 197extern void sys_sleep (int);
190extern int sys_link (const char *, const char *); 198extern int sys_link (const char *, const char *);
diff --git a/src/w32proc.c b/src/w32proc.c
index 3bdd9995340..43ecf4d68f3 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -812,6 +812,8 @@ new_child (void)
812 cp->pid = -1; 812 cp->pid = -1;
813 cp->procinfo.hProcess = NULL; 813 cp->procinfo.hProcess = NULL;
814 cp->status = STATUS_READ_ERROR; 814 cp->status = STATUS_READ_ERROR;
815 cp->input_file = NULL;
816 cp->pending_deletion = 0;
815 817
816 /* use manual reset event so that select() will function properly */ 818 /* use manual reset event so that select() will function properly */
817 cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL); 819 cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
@@ -860,6 +862,21 @@ delete_child (child_process *cp)
860 if (!CHILD_ACTIVE (cp)) 862 if (!CHILD_ACTIVE (cp))
861 return; 863 return;
862 864
865 /* Delete the child's temporary input file, if any, that is pending
866 deletion. */
867 if (cp->input_file)
868 {
869 if (cp->pending_deletion)
870 {
871 if (unlink (cp->input_file))
872 DebPrint (("delete_child.unlink (%s) failed, errno: %d\n",
873 cp->input_file, errno));
874 cp->pending_deletion = 0;
875 }
876 xfree (cp->input_file);
877 cp->input_file = NULL;
878 }
879
863 /* reap thread if necessary */ 880 /* reap thread if necessary */
864 if (cp->thrd) 881 if (cp->thrd)
865 { 882 {
@@ -1056,11 +1073,11 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
1056 This way the select emulator knows how to match file handles with 1073 This way the select emulator knows how to match file handles with
1057 entries in child_procs. */ 1074 entries in child_procs. */
1058void 1075void
1059register_child (int pid, int fd) 1076register_child (pid_t pid, int fd)
1060{ 1077{
1061 child_process *cp; 1078 child_process *cp;
1062 1079
1063 cp = find_child_pid (pid); 1080 cp = find_child_pid ((DWORD)pid);
1064 if (cp == NULL) 1081 if (cp == NULL)
1065 { 1082 {
1066 DebPrint (("register_child unable to find pid %lu\n", pid)); 1083 DebPrint (("register_child unable to find pid %lu\n", pid));
@@ -1087,6 +1104,45 @@ register_child (int pid, int fd)
1087 fd_info[fd].cp = cp; 1104 fd_info[fd].cp = cp;
1088} 1105}
1089 1106
1107/* Record INFILE as an input file for process PID. */
1108void
1109record_infile (pid_t pid, char *infile)
1110{
1111 child_process *cp;
1112
1113 /* INFILE should never be NULL, since xstrdup would have signaled
1114 memory full condition in that case, see callproc.c where this
1115 function is called. */
1116 eassert (infile);
1117
1118 cp = find_child_pid ((DWORD)pid);
1119 if (cp == NULL)
1120 {
1121 DebPrint (("record_infile is unable to find pid %lu\n", pid));
1122 return;
1123 }
1124
1125 cp->input_file = infile;
1126}
1127
1128/* Mark the input file INFILE of the corresponding subprocess as
1129 temporary, to be deleted when the subprocess exits. */
1130void
1131record_pending_deletion (char *infile)
1132{
1133 child_process *cp;
1134
1135 eassert (infile);
1136
1137 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
1138 if (CHILD_ACTIVE (cp)
1139 && cp->input_file && xstrcasecmp (cp->input_file, infile) == 0)
1140 {
1141 cp->pending_deletion = 1;
1142 break;
1143 }
1144}
1145
1090/* Called from waitpid when a process exits. */ 1146/* Called from waitpid when a process exits. */
1091static void 1147static void
1092reap_subprocess (child_process *cp) 1148reap_subprocess (child_process *cp)
@@ -1097,7 +1153,7 @@ reap_subprocess (child_process *cp)
1097#ifdef FULL_DEBUG 1153#ifdef FULL_DEBUG
1098 /* Process should have already died before we are called. */ 1154 /* Process should have already died before we are called. */
1099 if (WaitForSingleObject (cp->procinfo.hProcess, 0) != WAIT_OBJECT_0) 1155 if (WaitForSingleObject (cp->procinfo.hProcess, 0) != WAIT_OBJECT_0)
1100 DebPrint (("reap_subprocess: child fpr fd %d has not died yet!", cp->fd)); 1156 DebPrint (("reap_subprocess: child for fd %d has not died yet!", cp->fd));
1101#endif 1157#endif
1102 CloseHandle (cp->procinfo.hProcess); 1158 CloseHandle (cp->procinfo.hProcess);
1103 cp->procinfo.hProcess = NULL; 1159 cp->procinfo.hProcess = NULL;
@@ -1465,7 +1521,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
1465 Lisp_Object program, full; 1521 Lisp_Object program, full;
1466 char *cmdline, *env, *parg, **targ; 1522 char *cmdline, *env, *parg, **targ;
1467 int arglen, numenv; 1523 int arglen, numenv;
1468 int pid; 1524 pid_t pid;
1469 child_process *cp; 1525 child_process *cp;
1470 int is_dos_app, is_cygnus_app, is_gui_app; 1526 int is_dos_app, is_cygnus_app, is_gui_app;
1471 int do_quoting = 0; 1527 int do_quoting = 0;
@@ -2129,7 +2185,7 @@ find_child_console (HWND hwnd, LPARAM arg)
2129 2185
2130/* Emulate 'kill', but only for other processes. */ 2186/* Emulate 'kill', but only for other processes. */
2131int 2187int
2132sys_kill (int pid, int sig) 2188sys_kill (pid_t pid, int sig)
2133{ 2189{
2134 child_process *cp; 2190 child_process *cp;
2135 HANDLE proc_hand; 2191 HANDLE proc_hand;