From: Junio C Hamano Date: Tue, 30 May 2017 02:16:41 +0000 (+0900) Subject: Merge branch 'bw/forking-and-threading' X-Git-Tag: v2.14.0-rc0~145 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7d5e13f652b4dfbf5e399dd2de32e5954368f0f8?ds=inline;hp=-c Merge branch 'bw/forking-and-threading' The "run-command" API implementation has been made more robust against dead-locking in a threaded environment. * bw/forking-and-threading: usage.c: drop set_error_handle() run-command: restrict PATH search to executable files run-command: expose is_executable function run-command: block signals between fork and execve run-command: add note about forking and threading run-command: handle dup2 and close errors in child run-command: eliminate calls to error handling functions in child run-command: don't die in child when duping /dev/null run-command: prepare child environment before forking string-list: add string_list_remove function run-command: use the async-signal-safe execv instead of execvp run-command: prepare command before forking t0061: run_command executes scripts without a #! line t5550: use write_script to generate post-update hook --- 7d5e13f652b4dfbf5e399dd2de32e5954368f0f8 diff --combined git-compat-util.h index 98670a3c9a,f1f2a2d731..4b7dcf21ad --- a/git-compat-util.h +++ b/git-compat-util.h @@@ -319,11 -319,6 +319,11 @@@ extern char *gitdirname(char *) #define PRIo32 "o" #endif +typedef uintmax_t timestamp_t; +#define PRItime PRIuMAX +#define parse_timestamp strtoumax +#define TIME_MAX UINTMAX_MAX + #ifndef PATH_SEP #define PATH_SEP ':' #endif @@@ -450,7 -445,6 +450,6 @@@ extern void (*get_error_routine(void))( extern void set_warn_routine(void (*routine)(const char *warn, va_list params)); extern void (*get_warn_routine(void))(const char *warn, va_list params); extern void set_die_is_recursing_routine(int (*routine)(void)); - extern void set_error_handle(FILE *); extern int starts_with(const char *str, const char *prefix); @@@ -621,7 -615,7 +620,7 @@@ extern int git_lstat(const char *, stru #endif #define DEFAULT_PACKED_GIT_LIMIT \ - ((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? 8192 : 256)) + ((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? (32 * 1024L * 1024L) : 256)) #ifdef NO_PREAD #define pread git_pread @@@ -889,12 -883,6 +888,12 @@@ static inline size_t xsize_t(off_t len __attribute__((format (printf, 3, 4))) extern int xsnprintf(char *dst, size_t max, const char *fmt, ...); +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 256 +#endif + +extern int xgethostname(char *buf, size_t len); + /* in ctype.c, for kwset users */ extern const unsigned char tolower_trans_tbl[256]; @@@ -1069,15 -1057,6 +1068,15 @@@ static inline int regexec_buf(const reg #define HAVE_VARIADIC_MACROS 1 #endif +#ifdef HAVE_VARIADIC_MACROS +__attribute__((format (printf, 3, 4))) NORETURN +void BUG_fl(const char *file, int line, const char *fmt, ...); +#define BUG(...) BUG_fl(__FILE__, __LINE__, __VA_ARGS__) +#else +__attribute__((format (printf, 1, 2))) NORETURN +void BUG(const char *fmt, ...); +#endif + /* * Preserves errno, prints a message, but gives no warning for ENOENT. * Returns 0 on success, which includes trying to unlink an object that does diff --combined help.c index a07f01e6f9,0c65a2d21c..db7f3d79a0 --- a/help.c +++ b/help.c @@@ -1,6 -1,7 +1,7 @@@ #include "cache.h" #include "builtin.h" #include "exec_cmd.h" + #include "run-command.h" #include "levenshtein.h" #include "help.h" #include "common-cmds.h" @@@ -96,48 -97,6 +97,6 @@@ static void pretty_print_cmdnames(struc string_list_clear(&list, 0); } - static int is_executable(const char *name) - { - struct stat st; - - if (stat(name, &st) || /* stat, not lstat */ - !S_ISREG(st.st_mode)) - return 0; - - #if defined(GIT_WINDOWS_NATIVE) - /* - * On Windows there is no executable bit. The file extension - * indicates whether it can be run as an executable, and Git - * has special-handling to detect scripts and launch them - * through the indicated script interpreter. We test for the - * file extension first because virus scanners may make - * it quite expensive to open many files. - */ - if (ends_with(name, ".exe")) - return S_IXUSR; - - { - /* - * Now that we know it does not have an executable extension, - * peek into the file instead. - */ - char buf[3] = { 0 }; - int n; - int fd = open(name, O_RDONLY); - st.st_mode &= ~S_IXUSR; - if (fd >= 0) { - n = read(fd, buf, 2); - if (n == 2) - /* look for a she-bang */ - if (!strcmp(buf, "#!")) - st.st_mode |= S_IXUSR; - close(fd); - } - } - #endif - return st.st_mode & S_IXUSR; - } - static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) @@@ -411,8 -370,8 +370,8 @@@ const char *help_unknown_cmd(const cha if (SIMILAR_ENOUGH(best_similarity)) { fprintf_ln(stderr, - Q_("\nDid you mean this?", - "\nDid you mean one of these?", + Q_("\nThe most similar command is", + "\nThe most similar commands are", n)); for (i = 0; i < n; i++) diff --combined string-list.c index 003ca1879e,8f7b69ada1..c650500c6e --- a/string-list.c +++ b/string-list.c @@@ -41,7 -41,10 +41,7 @@@ static int add_entry(int insert_at, str if (exact_match) return -1 - index; - if (list->nr + 1 >= list->alloc) { - list->alloc += 32; - REALLOC_ARRAY(list->items, list->alloc); - } + ALLOC_GROW(list->items, list->nr+1, list->alloc); if (index < list->nr) memmove(list->items + index + 1, list->items + index, (list->nr - index) @@@ -64,6 -67,24 +64,24 @@@ struct string_list_item *string_list_in return list->items + index; } + void string_list_remove(struct string_list *list, const char *string, + int free_util) + { + int exact_match; + int i = get_entry_index(list, string, &exact_match); + + if (exact_match) { + if (list->strdup_strings) + free(list->items[i].string); + if (free_util) + free(list->items[i].util); + + list->nr--; + memmove(list->items + i, list->items + i + 1, + (list->nr - i) * sizeof(struct string_list_item)); + } + } + int string_list_has_string(const struct string_list *list, const char *string) { int exact_match; diff --combined usage.c index 1f63e033e9,2623c078e1..2f87ca69a8 --- a/usage.c +++ b/usage.c @@@ -6,12 -6,9 +6,9 @@@ #include "git-compat-util.h" #include "cache.h" - static FILE *error_handle; - void vreportf(const char *prefix, const char *err, va_list params) { char msg[4096]; - FILE *fh = error_handle ? error_handle : stderr; char *p; vsnprintf(msg, sizeof(msg), err, params); @@@ -19,7 -16,7 +16,7 @@@ if (iscntrl(*p) && *p != '\t' && *p != '\n') *p = '?'; } - fprintf(fh, "%s%s\n", prefix, msg); + fprintf(stderr, "%s%s\n", prefix, msg); } static NORETURN void usage_builtin(const char *err, va_list params) @@@ -88,11 -85,6 +85,6 @@@ void set_die_is_recursing_routine(int ( die_is_recursing = routine; } - void set_error_handle(FILE *fh) - { - error_handle = fh; - } - void NORETURN usagef(const char *err, ...) { va_list params; @@@ -201,35 -193,3 +193,35 @@@ void warning(const char *warn, ... warn_routine(warn, params); va_end(params); } + +static NORETURN void BUG_vfl(const char *file, int line, const char *fmt, va_list params) +{ + char prefix[256]; + + /* truncation via snprintf is OK here */ + if (file) + snprintf(prefix, sizeof(prefix), "BUG: %s:%d: ", file, line); + else + snprintf(prefix, sizeof(prefix), "BUG: "); + + vreportf(prefix, fmt, params); + abort(); +} + +#ifdef HAVE_VARIADIC_MACROS +NORETURN void BUG_fl(const char *file, int line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + BUG_vfl(file, line, fmt, ap); + va_end(ap); +} +#else +NORETURN void BUG(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + BUG_vfl(NULL, 0, fmt, ap); + va_end(ap); +} +#endif