diff options
| author | Paul Eggert | 2013-07-14 19:56:17 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-07-14 19:56:17 -0700 |
| commit | bafe80ce49206c61bea74b0c70080bfdc97785d1 (patch) | |
| tree | 22253f5fabd4df1513fe28e403280cf5d4e98e28 /src | |
| parent | 0463c1ef26bf2d3dc3ea8a3de20e4446c1a55e64 (diff) | |
| download | emacs-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/ChangeLog | 15 | ||||
| -rw-r--r-- | src/callproc.c | 136 |
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 @@ | |||
| 1 | 2013-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 | |||
| 1 | 2013-07-14 Paul Eggert <eggert@cs.ucla.edu> | 16 | 2013-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 | ||
| 963 | DEFUN ("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. */ |
| 966 | The remaining arguments are optional. | ||
| 967 | Delete the text if fourth arg DELETE is non-nil. | ||
| 968 | |||
| 969 | Insert 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). | ||
| 973 | BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | ||
| 974 | REAL-BUFFER says what to do with standard output, as above, | ||
| 975 | while STDERR-FILE says what to do with standard error in the child. | ||
| 976 | STDERR-FILE may be nil (discard standard error output), | ||
| 977 | t (mix it with ordinary output), or a file name string. | ||
| 978 | |||
| 979 | Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted. | ||
| 980 | Remaining args are passed to PROGRAM at startup as command args. | ||
| 981 | 966 | ||
| 982 | If BUFFER is 0, `call-process-region' returns immediately with value nil. | 967 | static Lisp_Object |
| 983 | Otherwise it waits for PROGRAM to terminate | 968 | create_temp_file (ptrdiff_t nargs, Lisp_Object *args) |
| 984 | and returns a numeric exit status or a signal description string. | ||
| 985 | If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | ||
| 986 | |||
| 987 | usage: (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 | |||
| 1077 | DEFUN ("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. | ||
| 1080 | The remaining arguments are optional. | ||
| 1081 | Delete the text if fourth arg DELETE is non-nil. | ||
| 1082 | |||
| 1083 | Insert 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). | ||
| 1087 | BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case, | ||
| 1088 | REAL-BUFFER says what to do with standard output, as above, | ||
| 1089 | while STDERR-FILE says what to do with standard error in the child. | ||
| 1090 | STDERR-FILE may be nil (discard standard error output), | ||
| 1091 | t (mix it with ordinary output), or a file name string. | ||
| 1092 | |||
| 1093 | Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted. | ||
| 1094 | Remaining args are passed to PROGRAM at startup as command args. | ||
| 1095 | |||
| 1096 | If BUFFER is 0, `call-process-region' returns immediately with value nil. | ||
| 1097 | Otherwise it waits for PROGRAM to terminate | ||
| 1098 | and returns a numeric exit status or a signal description string. | ||
| 1099 | If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | ||
| 1100 | |||
| 1101 | usage: (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); |