aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-07-14 19:56:17 -0700
committerPaul Eggert2013-07-14 19:56:17 -0700
commitbafe80ce49206c61bea74b0c70080bfdc97785d1 (patch)
tree22253f5fabd4df1513fe28e403280cf5d4e98e28 /src
parent0463c1ef26bf2d3dc3ea8a3de20e4446c1a55e64 (diff)
downloademacs-bafe80ce49206c61bea74b0c70080bfdc97785d1.tar.gz
emacs-bafe80ce49206c61bea74b0c70080bfdc97785d1.zip
* callproc.c (Fcall_process_region): Fix minor race and tune.
(create_temp_file): New function, with the temp-file-creation part of the old Fcall_process_region. Use Fcopy_sequence to create the temp file name, rather than alloca + build_string, for simplicity. Don't bother to block input around the temp file creation; shouldn't be needed. Simplify use of mktemp. Use record_unwind_protect immediately after creating the temp file; this closes an unlikely race where the temp file was not removed. Use memcpy rather than an open-coded loop. (Fcall_process_region): Use the new function. If the input is empty, redirect from /dev/null rather than from a newly created empty temp file; this avoids unnecessary file system traffic.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/callproc.c136
2 files changed, 92 insertions, 59 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 329fa6ba670..cd6d188b686 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
12013-07-15 Paul Eggert <eggert@cs.ucla.edu>
2
3 * callproc.c (Fcall_process_region): Fix minor race and tune.
4 (create_temp_file): New function, with the temp-file-creation part
5 of the old Fcall_process_region. Use Fcopy_sequence to create the
6 temp file name, rather than alloca + build_string, for simplicity.
7 Don't bother to block input around the temp file creation;
8 shouldn't be needed. Simplify use of mktemp. Use
9 record_unwind_protect immediately after creating the temp file;
10 this closes an unlikely race where the temp file was not removed.
11 Use memcpy rather than an open-coded loop.
12 (Fcall_process_region): Use the new function. If the input is
13 empty, redirect from /dev/null rather than from a newly created
14 empty temp file; this avoids unnecessary file system traffic.
15
12013-07-14 Paul Eggert <eggert@cs.ucla.edu> 162013-07-14 Paul Eggert <eggert@cs.ucla.edu>
2 17
3 * filelock.c (create_lock_file) [!HAVE_MKOSTEMP && !HAVE_MKSTEMP]: 18 * filelock.c (create_lock_file) [!HAVE_MKOSTEMP && !HAVE_MKSTEMP]:
diff --git a/src/callproc.c b/src/callproc.c
index cdf92422b4d..6d770f881ff 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -960,41 +960,16 @@ delete_temp_file (Lisp_Object name)
960 return Qnil; 960 return Qnil;
961} 961}
962 962
963DEFUN ("call-process-region", Fcall_process_region, Scall_process_region, 963/* Create a temporary file suitable for storing the input data of
964 3, MANY, 0, 964 call-process-region. NARGS and ARGS are the same as for
965 doc: /* Send text from START to END to a synchronous process running PROGRAM. 965 call-process-region. */
966The remaining arguments are optional.
967Delete the text if fourth arg DELETE is non-nil.
968
969Insert output in BUFFER before point; t means current buffer; nil for
970 BUFFER means discard it; 0 means discard and don't wait; and `(:file
971 FILE)', where FILE is a file name string, means that it should be
972 written to that file (if the file already exists it is overwritten).
973BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
974REAL-BUFFER says what to do with standard output, as above,
975while STDERR-FILE says what to do with standard error in the child.
976STDERR-FILE may be nil (discard standard error output),
977t (mix it with ordinary output), or a file name string.
978
979Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.
980Remaining args are passed to PROGRAM at startup as command args.
981 966
982If BUFFER is 0, `call-process-region' returns immediately with value nil. 967static Lisp_Object
983Otherwise it waits for PROGRAM to terminate 968create_temp_file (ptrdiff_t nargs, Lisp_Object *args)
984and returns a numeric exit status or a signal description string.
985If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
986
987usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
988 (ptrdiff_t nargs, Lisp_Object *args)
989{ 969{
990 struct gcpro gcpro1; 970 struct gcpro gcpro1;
991 Lisp_Object filename_string; 971 Lisp_Object filename_string;
992 register Lisp_Object start, end; 972 Lisp_Object val, start, end;
993 ptrdiff_t count = SPECPDL_INDEX ();
994 /* Qt denotes we have not yet called Ffind_operation_coding_system. */
995 Lisp_Object coding_systems;
996 Lisp_Object val, *args2;
997 ptrdiff_t i;
998 Lisp_Object tmpdir; 973 Lisp_Object tmpdir;
999 974
1000 if (STRINGP (Vtemporary_file_directory)) 975 if (STRINGP (Vtemporary_file_directory))
@@ -1016,9 +991,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1016 } 991 }
1017 992
1018 { 993 {
1019 USE_SAFE_ALLOCA;
1020 Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir); 994 Lisp_Object pattern = Fexpand_file_name (Vtemp_file_name_pattern, tmpdir);
1021 Lisp_Object encoded_tem;
1022 char *tempfile; 995 char *tempfile;
1023 996
1024#ifdef WINDOWSNT 997#ifdef WINDOWSNT
@@ -1036,39 +1009,30 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1036 } 1009 }
1037#endif 1010#endif
1038 1011
1039 encoded_tem = ENCODE_FILE (pattern); 1012 filename_string = Fcopy_sequence (ENCODE_FILE (pattern));
1040 tempfile = SAFE_ALLOCA (SBYTES (encoded_tem) + 1); 1013 GCPRO1 (filename_string);
1041 memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1); 1014 tempfile = SSDATA (filename_string);
1042 coding_systems = Qt;
1043 1015
1044#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
1045 { 1016 {
1046 int fd, open_errno; 1017 int fd;
1047 1018
1048 block_input (); 1019#ifdef HAVE_MKOSTEMP
1049# ifdef HAVE_MKOSTEMP
1050 fd = mkostemp (tempfile, O_CLOEXEC); 1020 fd = mkostemp (tempfile, O_CLOEXEC);
1051# else 1021#elif defined HAVE_MKSTEMP
1052 fd = mkstemp (tempfile); 1022 fd = mkstemp (tempfile);
1053# endif 1023#else
1054 open_errno = errno; 1024 errno = EEXIST;
1055 unblock_input (); 1025 mktemp (tempfile);
1026 /* INT_MAX denotes success, because close (INT_MAX) does nothing. */
1027 fd = *tempfile ? INT_MAX : -1;
1028#endif
1056 if (fd < 0) 1029 if (fd < 0)
1057 report_file_errno ("Failed to open temporary file", 1030 report_file_error ("Failed to open temporary file using pattern",
1058 Fcons (build_string (tempfile), Qnil), open_errno); 1031 Fcons (pattern, Qnil));
1059 emacs_close (fd); 1032 emacs_close (fd);
1060 } 1033 }
1061#else
1062 errno = EEXIST;
1063 mktemp (tempfile);
1064 if (!*tempfile)
1065 report_file_error ("Failed to open temporary file using pattern",
1066 Fcons (pattern, Qnil));
1067#endif
1068 1034
1069 filename_string = build_string (tempfile); 1035 record_unwind_protect (delete_temp_file, filename_string);
1070 GCPRO1 (filename_string);
1071 SAFE_FREE ();
1072 } 1036 }
1073 1037
1074 start = args[0]; 1038 start = args[0];
@@ -1080,10 +1044,12 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1080 val = Qraw_text; 1044 val = Qraw_text;
1081 else 1045 else
1082 { 1046 {
1047 Lisp_Object coding_systems;
1048 Lisp_Object *args2;
1083 USE_SAFE_ALLOCA; 1049 USE_SAFE_ALLOCA;
1084 SAFE_NALLOCA (args2, 1, nargs + 1); 1050 SAFE_NALLOCA (args2, 1, nargs + 1);
1085 args2[0] = Qcall_process_region; 1051 args2[0] = Qcall_process_region;
1086 for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; 1052 memcpy (args2 + 1, args, nargs * sizeof *args);
1087 coding_systems = Ffind_operation_coding_system (nargs + 1, args2); 1053 coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
1088 val = CONSP (coding_systems) ? XCDR (coding_systems) : Qnil; 1054 val = CONSP (coding_systems) ? XCDR (coding_systems) : Qnil;
1089 SAFE_FREE (); 1055 SAFE_FREE ();
@@ -1105,7 +1071,59 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1105 /* Note that Fcall_process takes care of binding 1071 /* Note that Fcall_process takes care of binding
1106 coding-system-for-read. */ 1072 coding-system-for-read. */
1107 1073
1108 record_unwind_protect (delete_temp_file, filename_string); 1074 RETURN_UNGCPRO (filename_string);
1075}
1076
1077DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
1078 3, MANY, 0,
1079 doc: /* Send text from START to END to a synchronous process running PROGRAM.
1080The remaining arguments are optional.
1081Delete the text if fourth arg DELETE is non-nil.
1082
1083Insert output in BUFFER before point; t means current buffer; nil for
1084 BUFFER means discard it; 0 means discard and don't wait; and `(:file
1085 FILE)', where FILE is a file name string, means that it should be
1086 written to that file (if the file already exists it is overwritten).
1087BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
1088REAL-BUFFER says what to do with standard output, as above,
1089while STDERR-FILE says what to do with standard error in the child.
1090STDERR-FILE may be nil (discard standard error output),
1091t (mix it with ordinary output), or a file name string.
1092
1093Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.
1094Remaining args are passed to PROGRAM at startup as command args.
1095
1096If BUFFER is 0, `call-process-region' returns immediately with value nil.
1097Otherwise it waits for PROGRAM to terminate
1098and returns a numeric exit status or a signal description string.
1099If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
1100
1101usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
1102 (ptrdiff_t nargs, Lisp_Object *args)
1103{
1104 struct gcpro gcpro1;
1105 Lisp_Object filename_string;
1106 ptrdiff_t count = SPECPDL_INDEX ();
1107 Lisp_Object start = args[0];
1108 Lisp_Object end = args[1];
1109 bool empty_input;
1110
1111 if (STRINGP (start))
1112 empty_input = SCHARS (start) == 0;
1113 else if (NILP (start))
1114 empty_input = BEG == Z;
1115 else
1116 {
1117 validate_region (&args[0], &args[1]);
1118 start = args[0];
1119 end = args[1];
1120 empty_input = XINT (start) == XINT (end);
1121 }
1122
1123 filename_string = (empty_input
1124 ? build_string (NULL_DEVICE)
1125 : create_temp_file (nargs, args));
1126 GCPRO1 (filename_string);
1109 1127
1110 if (nargs > 3 && !NILP (args[3])) 1128 if (nargs > 3 && !NILP (args[3]))
1111 Fdelete_region (start, end); 1129 Fdelete_region (start, end);