diff options
Diffstat (limited to 'compat')
| -rw-r--r-- | compat/compiler.h | 4 | ||||
| -rw-r--r-- | compat/fsmonitor/fsm-ipc-darwin.c | 2 | ||||
| -rw-r--r-- | compat/fsmonitor/fsm-listen-darwin.c | 6 | ||||
| -rw-r--r-- | compat/fsmonitor/fsm-listen-win32.c | 10 | ||||
| -rw-r--r-- | compat/mingw.c | 199 | ||||
| -rw-r--r-- | compat/mingw.h | 18 | ||||
| -rw-r--r-- | compat/nedmalloc/nedmalloc.c | 2 | ||||
| -rw-r--r-- | compat/precompose_utf8.c | 1 | ||||
| -rw-r--r-- | compat/regex/regcomp.c | 2 | ||||
| -rw-r--r-- | compat/regex/regexec.c | 2 | ||||
| -rw-r--r-- | compat/simple-ipc/ipc-shared.c | 5 | ||||
| -rw-r--r-- | compat/simple-ipc/ipc-unix-socket.c | 30 | ||||
| -rw-r--r-- | compat/simple-ipc/ipc-win32.c | 48 | ||||
| -rw-r--r-- | compat/stub/procinfo.c | 2 | ||||
| -rw-r--r-- | compat/terminal.c | 2 | ||||
| -rw-r--r-- | compat/vcbuild/include/unistd.h | 4 | ||||
| -rw-r--r-- | compat/win32/headless.c | 2 | ||||
| -rw-r--r-- | compat/win32/path-utils.c | 2 | ||||
| -rw-r--r-- | compat/win32/pthread.c | 2 | ||||
| -rw-r--r-- | compat/win32/pthread.h | 4 | ||||
| -rw-r--r-- | compat/win32/syslog.c | 2 | ||||
| -rw-r--r-- | compat/win32mmap.c | 2 | ||||
| -rw-r--r-- | compat/winansi.c | 2 |
23 files changed, 296 insertions, 57 deletions
diff --git a/compat/compiler.h b/compat/compiler.h index e9ad9db84f..e12e426404 100644 --- a/compat/compiler.h +++ b/compat/compiler.h @@ -9,7 +9,7 @@ static inline void get_compiler_info(struct strbuf *info) { - int len = info->len; + size_t len = info->len; #ifdef __clang__ strbuf_addf(info, "clang: %s\n", __clang_version__); #elif defined(__GNUC__) @@ -27,7 +27,7 @@ static inline void get_compiler_info(struct strbuf *info) static inline void get_libc_info(struct strbuf *info) { - int len = info->len; + size_t len = info->len; #ifdef __GLIBC__ strbuf_addf(info, "glibc: %s\n", gnu_get_libc_version()); diff --git a/compat/fsmonitor/fsm-ipc-darwin.c b/compat/fsmonitor/fsm-ipc-darwin.c index 52f4f29720..fe149a1b37 100644 --- a/compat/fsmonitor/fsm-ipc-darwin.c +++ b/compat/fsmonitor/fsm-ipc-darwin.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "config.h" #include "gettext.h" diff --git a/compat/fsmonitor/fsm-listen-darwin.c b/compat/fsmonitor/fsm-listen-darwin.c index 2fc67442eb..dfa551459d 100644 --- a/compat/fsmonitor/fsm-listen-darwin.c +++ b/compat/fsmonitor/fsm-listen-darwin.c @@ -516,6 +516,12 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state) } data->stream_started = 1; + /* + * Our fs event listener is now running, so it's safe to start + * serving client requests. + */ + ipc_server_start_async(state->ipc_server_data); + pthread_mutex_lock(&data->dq_lock); pthread_cond_wait(&data->dq_finished, &data->dq_lock); pthread_mutex_unlock(&data->dq_lock); diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c index 5a21dade7b..9a6efc9bea 100644 --- a/compat/fsmonitor/fsm-listen-win32.c +++ b/compat/fsmonitor/fsm-listen-win32.c @@ -431,9 +431,9 @@ static int recv_rdcw_watch(struct one_watch *watch) * but I observed ERROR_ACCESS_DENIED (0x05) errors during * testing. * - * Note that we only get notificaiton events for events + * Note that we only get notification events for events * *within* the directory, not *on* the directory itself. - * (These might be properies of the parent directory, for + * (These might be properties of the parent directory, for * example). * * NEEDSWORK: We might try to check for the deleted directory @@ -741,6 +741,12 @@ void fsm_listen__loop(struct fsmonitor_daemon_state *state) start_rdcw_watch(data->watch_gitdir) == -1) goto force_error_stop; + /* + * Now that we've established the rdcw watches, we can start + * serving clients. + */ + ipc_server_start_async(state->ipc_server_data); + for (;;) { dwWait = WaitForMultipleObjects(data->nr_listener_handles, data->hListener, diff --git a/compat/mingw.c b/compat/mingw.c index 29d3f09768..63f36c893b 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "../git-compat-util.h" #include "win32.h" #include <aclapi.h> @@ -243,7 +245,8 @@ static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY; static char *unset_environment_variables; int mingw_core_config(const char *var, const char *value, - const struct config_context *ctx, void *cb) + const struct config_context *ctx UNUSED, + void *cb UNUSED) { if (!strcmp(var, "core.hidedotfiles")) { if (value && !strcasecmp(value, "dotgitonly")) @@ -453,7 +456,7 @@ static int set_hidden_flag(const wchar_t *path, int set) return -1; } -int mingw_mkdir(const char *path, int mode) +int mingw_mkdir(const char *path, int mode UNUSED) { int ret; wchar_t wpath[MAX_PATH]; @@ -499,7 +502,7 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) * to append to the file. */ handle = CreateFileW(wfilename, FILE_APPEND_DATA, - FILE_SHARE_WRITE | FILE_SHARE_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); @@ -530,6 +533,70 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) } /* + * Ideally, we'd use `_wopen()` to implement this functionality so that we + * don't have to reimplement it, but unfortunately we do not have tight control + * over the share mode there. And while `_wsopen()` and friends exist that give + * us _some_ control over the share mode, this family of functions doesn't give + * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict + * requirement for us though so that we can unlink or rename over files that + * are held open by another process. + * + * We are thus forced to implement our own emulation of `open()`. To make our + * life simpler we only implement basic support for this, namely opening + * existing files for reading and/or writing. This means that newly created + * files won't have their sharing mode set up correctly, but for now I couldn't + * find any case where this matters. We may have to revisit that in the future + * though based on our needs. + */ +static int mingw_open_existing(const wchar_t *filename, int oflags, ...) +{ + SECURITY_ATTRIBUTES security_attributes = { + .nLength = sizeof(security_attributes), + .bInheritHandle = !(oflags & O_NOINHERIT), + }; + HANDLE handle; + DWORD access; + int fd; + + /* We only support basic flags. */ + if (oflags & ~(O_ACCMODE | O_NOINHERIT)) { + errno = ENOSYS; + return -1; + } + + switch (oflags & O_ACCMODE) { + case O_RDWR: + access = GENERIC_READ | GENERIC_WRITE; + break; + case O_WRONLY: + access = GENERIC_WRITE; + break; + default: + access = GENERIC_READ; + break; + } + + handle = CreateFileW(filename, access, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + DWORD err = GetLastError(); + + /* See `mingw_open_append()` for why we have this conversion. */ + if (err == ERROR_INVALID_PARAMETER) + err = ERROR_PATH_NOT_FOUND; + + errno = err_win_to_posix(err); + return -1; + } + + fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY); + if (fd < 0) + CloseHandle(handle); + return fd; +} + +/* * Does the pathname map to the local named pipe filesystem? * That is, does it have a "//./pipe/" prefix? */ @@ -564,6 +631,8 @@ int mingw_open (const char *filename, int oflags, ...) if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename)) open_fn = mingw_open_append; + else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT))) + open_fn = mingw_open_existing; else open_fn = _wopen; @@ -597,7 +666,7 @@ int mingw_open (const char *filename, int oflags, ...) return fd; } -static BOOL WINAPI ctrl_ignore(DWORD type) +static BOOL WINAPI ctrl_ignore(DWORD type UNUSED) { return TRUE; } @@ -779,7 +848,7 @@ static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts) */ static int has_valid_directory_prefix(wchar_t *wfilename) { - int n = wcslen(wfilename); + size_t n = wcslen(wfilename); while (n > 0) { wchar_t c = wfilename[--n]; @@ -888,7 +957,7 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf) */ static int do_stat_internal(int follow, const char *file_name, struct stat *buf) { - int namelen; + size_t namelen; char alt_name[PATH_MAX]; if (!do_lstat(follow, file_name, buf)) @@ -1003,7 +1072,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times) osfilehandle = CreateFileW(wfilename, FILE_WRITE_ATTRIBUTES, - 0 /*FileShare.None*/, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, (attrs != INVALID_FILE_ATTRIBUTES && @@ -1085,7 +1154,7 @@ int mkstemp(char *template) return git_mkstemp_mode(template, 0600); } -int gettimeofday(struct timeval *tv, void *tz) +int gettimeofday(struct timeval *tv, void *tz UNUSED) { FILETIME ft; long long hnsec; @@ -1271,7 +1340,8 @@ static const char *parse_interpreter(const char *cmd) { static char buf[100]; char *p, *opt; - int n, fd; + ssize_t n; /* read() can return negative values */ + int fd; /* don't even try a .exe */ n = strlen(cmd); @@ -1336,7 +1406,7 @@ static char *path_lookup(const char *cmd, int exe_only) { const char *path; char *prog = NULL; - int len = strlen(cmd); + size_t len = strlen(cmd); int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe"); if (strpbrk(cmd, "/\\")) @@ -1953,7 +2023,7 @@ char *mingw_getenv(const char *name) #define GETENV_MAX_RETAIN 64 static char *values[GETENV_MAX_RETAIN]; static int value_counter; - int len_key, len_value; + size_t len_key, len_value; wchar_t *w_key; char *value; wchar_t w_value[32768]; @@ -1965,7 +2035,8 @@ char *mingw_getenv(const char *name) /* We cannot use xcalloc() here because that uses getenv() itself */ w_key = calloc(len_key, sizeof(wchar_t)); if (!w_key) - die("Out of memory, (tried to allocate %u wchar_t's)", len_key); + die("Out of memory, (tried to allocate %"PRIuMAX" wchar_t's)", + (uintmax_t)len_key); xutftowcs(w_key, name, len_key); /* GetEnvironmentVariableW() only sets the last error upon failure */ SetLastError(ERROR_SUCCESS); @@ -1980,7 +2051,8 @@ char *mingw_getenv(const char *name) /* We cannot use xcalloc() here because that uses getenv() itself */ value = calloc(len_value, sizeof(char)); if (!value) - die("Out of memory, (tried to allocate %u bytes)", len_value); + die("Out of memory, (tried to allocate %"PRIuMAX" bytes)", + (uintmax_t)len_value); xwcstoutf(value, w_value, len_value); /* @@ -1998,7 +2070,7 @@ char *mingw_getenv(const char *name) int mingw_putenv(const char *namevalue) { - int size; + size_t size; wchar_t *wide, *equal; BOOL result; @@ -2008,7 +2080,8 @@ int mingw_putenv(const char *namevalue) size = strlen(namevalue) * 2 + 1; wide = calloc(size, sizeof(wchar_t)); if (!wide) - die("Out of memory, (tried to allocate %u wchar_t's)", size); + die("Out of memory, (tried to allocate %" PRIuMAX " wchar_t's)", + (uintmax_t)size); xutftowcs(wide, namevalue, size); equal = wcschr(wide, L'='); if (!equal) @@ -2148,10 +2221,16 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz) #undef rename int mingw_rename(const char *pold, const char *pnew) { + static int supports_file_rename_info_ex = 1; DWORD attrs, gle; int tries = 0; wchar_t wpold[MAX_PATH], wpnew[MAX_PATH]; - if (xutftowcs_path(wpold, pold) < 0 || xutftowcs_path(wpnew, pnew) < 0) + int wpnew_len; + + if (xutftowcs_path(wpold, pold) < 0) + return -1; + wpnew_len = xutftowcs_path(wpnew, pnew); + if (wpnew_len < 0) return -1; /* @@ -2162,11 +2241,84 @@ int mingw_rename(const char *pold, const char *pnew) return 0; if (errno != EEXIST) return -1; + repeat: - if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING)) - return 0; + if (supports_file_rename_info_ex) { + /* + * Our minimum required Windows version is still set to Windows + * Vista. We thus have to declare required infrastructure for + * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to + * 0x0A00. Furthermore, we have to handle cases where the + * FileRenameInfoEx call isn't supported yet. + */ +#define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001 +#define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002 + FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22; + struct { + /* + * This is usually an unnamed union, but that is not + * part of ISO C99. We thus inline the field, as we + * really only care for the Flags field anyway. + */ + DWORD Flags; + HANDLE RootDirectory; + DWORD FileNameLength; + /* + * The actual structure is defined with a single-character + * flex array so that the structure has to be allocated on + * the heap. As we declare this structure ourselves though + * we can avoid the allocation and define FileName to have + * MAX_PATH bytes. + */ + WCHAR FileName[MAX_PATH]; + } rename_info = { 0 }; + HANDLE old_handle = INVALID_HANDLE_VALUE; + BOOL success; + + old_handle = CreateFileW(wpold, DELETE, + FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (old_handle == INVALID_HANDLE_VALUE) { + errno = err_win_to_posix(GetLastError()); + return -1; + } + + rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS | + FILE_RENAME_FLAG_POSIX_SEMANTICS; + rename_info.FileNameLength = wpnew_len * sizeof(WCHAR); + memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR)); + + success = SetFileInformationByHandle(old_handle, FileRenameInfoEx, + &rename_info, sizeof(rename_info)); + gle = GetLastError(); + CloseHandle(old_handle); + if (success) + return 0; + + /* + * When we see ERROR_INVALID_PARAMETER we can assume that the + * current system doesn't support FileRenameInfoEx. Keep us + * from using it in future calls and retry. + */ + if (gle == ERROR_INVALID_PARAMETER) { + supports_file_rename_info_ex = 0; + goto repeat; + } + + /* + * In theory, we shouldn't get ERROR_ACCESS_DENIED because we + * always open files with FILE_SHARE_DELETE But in practice we + * cannot assume that Git is the only one accessing files, and + * other applications may not set FILE_SHARE_DELETE. So we have + * to retry. + */ + } else { + if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING)) + return 0; + gle = GetLastError(); + } + /* TODO: translate more errors */ - gle = GetLastError(); if (gle == ERROR_ACCESS_DENIED && (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { @@ -2252,7 +2404,7 @@ char *mingw_query_user_email(void) return get_extended_user_info(NameUserPrincipal); } -struct passwd *getpwuid(int uid) +struct passwd *getpwuid(int uid UNUSED) { static unsigned initialized; static char user_name[100]; @@ -2304,7 +2456,7 @@ static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL; * length to call the signal handler. */ -static unsigned __stdcall ticktack(void *dummy) +static unsigned __stdcall ticktack(void *dummy UNUSED) { while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) { mingw_raise(SIGALRM); @@ -2352,7 +2504,7 @@ static inline int is_timeval_eq(const struct timeval *i1, const struct timeval * return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec; } -int setitimer(int type, struct itimerval *in, struct itimerval *out) +int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out) { static const struct timeval zero; static int atexit_done; @@ -3082,7 +3234,8 @@ static void maybe_redirect_std_handles(void) */ int wmain(int argc, const wchar_t **wargv) { - int i, maxlen, exit_status; + int i, exit_status; + size_t maxlen; char *buffer, **save; const char **argv; diff --git a/compat/mingw.h b/compat/mingw.h index 27b61284f4..ebfb8ba423 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -122,17 +122,17 @@ struct utsname { * trivial stubs */ -static inline int readlink(const char *path, char *buf, size_t bufsiz) +static inline int readlink(const char *path UNUSED, char *buf UNUSED, size_t bufsiz UNUSED) { errno = ENOSYS; return -1; } -static inline int symlink(const char *oldpath, const char *newpath) +static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED) { errno = ENOSYS; return -1; } -static inline int fchmod(int fildes, mode_t mode) +static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED) { errno = ENOSYS; return -1; } #ifndef __MINGW64_VERSION_MAJOR static inline pid_t fork(void) { errno = ENOSYS; return -1; } #endif -static inline unsigned int alarm(unsigned int seconds) +static inline unsigned int alarm(unsigned int seconds UNUSED) { return 0; } static inline int fsync(int fd) { return _commit(fd); } @@ -140,9 +140,9 @@ static inline void sync(void) {} static inline uid_t getuid(void) { return 1; } -static inline struct passwd *getpwnam(const char *name) +static inline struct passwd *getpwnam(const char *name UNUSED) { return NULL; } -static inline int fcntl(int fd, int cmd, ...) +static inline int fcntl(int fd UNUSED, int cmd, ...) { if (cmd == F_GETFD || cmd == F_SETFD) return 0; @@ -151,17 +151,17 @@ static inline int fcntl(int fd, int cmd, ...) } #define sigemptyset(x) (void)0 -static inline int sigaddset(sigset_t *set, int signum) +static inline int sigaddset(sigset_t *set UNUSED, int signum UNUSED) { return 0; } #define SIG_BLOCK 0 #define SIG_UNBLOCK 0 -static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +static inline int sigprocmask(int how UNUSED, const sigset_t *set UNUSED, sigset_t *oldset UNUSED) { return 0; } static inline pid_t getppid(void) { return 1; } static inline pid_t getpgid(pid_t pid) { return pid == 0 ? getpid() : pid; } -static inline pid_t tcgetpgrp(int fd) +static inline pid_t tcgetpgrp(int fd UNUSED) { return getpid(); } /* diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c index 2c0ace7075..145255da43 100644 --- a/compat/nedmalloc/nedmalloc.c +++ b/compat/nedmalloc/nedmalloc.c @@ -31,6 +31,8 @@ DEALINGS IN THE SOFTWARE. /*#pragma optimize("a", on)*/ #endif +#pragma GCC diagnostic ignored "-Wunused-parameter" + /*#define FULLSANITYCHECKS*/ #include "nedmalloc.h" diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index 0bd5c24250..f7cc7b3be5 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -4,6 +4,7 @@ */ #define PRECOMPOSE_UNICODE_C +#define USE_THE_REPOSITORY_VARIABLE #include "git-compat-util.h" #include "config.h" diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c index 6c5d455e92..8d93a9b93f 100644 --- a/compat/regex/regcomp.c +++ b/compat/regex/regcomp.c @@ -17,6 +17,8 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ +#pragma GCC diagnostic ignored "-Wunused-parameter" + #if defined __TANDEM /* This is currently duplicated from git-compat-utils.h */ # ifdef NO_INTPTR_T diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c index e92be5741d..2eeec82f40 100644 --- a/compat/regex/regexec.c +++ b/compat/regex/regexec.c @@ -292,7 +292,7 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); concerned. If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stroed in REGS. (For the "_2" variants, the offsets are + and all groups are stored in REGS. (For the "_2" variants, the offsets are computed relative to the concatenation, not relative to the individual strings.) diff --git a/compat/simple-ipc/ipc-shared.c b/compat/simple-ipc/ipc-shared.c index cb176d966f..d1c21b49bd 100644 --- a/compat/simple-ipc/ipc-shared.c +++ b/compat/simple-ipc/ipc-shared.c @@ -16,11 +16,12 @@ int ipc_server_run(const char *path, const struct ipc_server_opts *opts, struct ipc_server_data *server_data = NULL; int ret; - ret = ipc_server_run_async(&server_data, path, opts, - application_cb, application_data); + ret = ipc_server_init_async(&server_data, path, opts, + application_cb, application_data); if (ret) return ret; + ipc_server_start_async(server_data); ret = ipc_server_await(server_data); ipc_server_free(server_data); diff --git a/compat/simple-ipc/ipc-unix-socket.c b/compat/simple-ipc/ipc-unix-socket.c index 9b3f2cdf8c..7db3b2a897 100644 --- a/compat/simple-ipc/ipc-unix-socket.c +++ b/compat/simple-ipc/ipc-unix-socket.c @@ -328,6 +328,7 @@ struct ipc_server_data { int back_pos; int front_pos; + int started; int shutdown_requested; int is_stopped; }; @@ -712,7 +713,7 @@ static int accept_thread__wait_for_connection( * Block SIGPIPE in this thread for the life of the thread. This * avoids any stray SIGPIPE signals when closing pipe fds under * extremely heavy loads (such as when the fifo queue is full and we - * drop incomming connections). + * drop incoming connections). */ static void *accept_thread_proc(void *_accept_thread_data) { @@ -824,10 +825,10 @@ static int setup_listener_socket( /* * Start IPC server in a pool of background threads. */ -int ipc_server_run_async(struct ipc_server_data **returned_server_data, - const char *path, const struct ipc_server_opts *opts, - ipc_server_application_cb *application_cb, - void *application_data) +int ipc_server_init_async(struct ipc_server_data **returned_server_data, + const char *path, const struct ipc_server_opts *opts, + ipc_server_application_cb *application_cb, + void *application_data) { struct unix_ss_socket *server_socket = NULL; struct ipc_server_data *server_data; @@ -888,6 +889,12 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, server_data->accept_thread->fd_send_shutdown = sv[0]; server_data->accept_thread->fd_wait_shutdown = sv[1]; + /* + * Hold work-available mutex so that no work can start until + * we unlock it. + */ + pthread_mutex_lock(&server_data->work_available_mutex); + if (pthread_create(&server_data->accept_thread->pthread_id, NULL, accept_thread_proc, server_data->accept_thread)) die_errno(_("could not start accept_thread '%s'"), path); @@ -918,6 +925,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, return 0; } +void ipc_server_start_async(struct ipc_server_data *server_data) +{ + if (!server_data || server_data->started) + return; + + server_data->started = 1; + pthread_mutex_unlock(&server_data->work_available_mutex); +} + /* * Gently tell the IPC server treads to shutdown. * Can be run on any thread. @@ -933,7 +949,9 @@ int ipc_server_stop_async(struct ipc_server_data *server_data) trace2_region_enter("ipc-server", "server-stop-async", NULL); - pthread_mutex_lock(&server_data->work_available_mutex); + /* If we haven't started yet, we are already holding lock. */ + if (server_data->started) + pthread_mutex_lock(&server_data->work_available_mutex); server_data->shutdown_requested = 1; diff --git a/compat/simple-ipc/ipc-win32.c b/compat/simple-ipc/ipc-win32.c index 8bfe51248e..a8fc812adf 100644 --- a/compat/simple-ipc/ipc-win32.c +++ b/compat/simple-ipc/ipc-win32.c @@ -371,6 +371,9 @@ struct ipc_server_data { HANDLE hEventStopRequested; struct ipc_server_thread_data *thread_list; int is_stopped; + + pthread_mutex_t startup_barrier; + int started; }; enum connect_result { @@ -526,6 +529,16 @@ static int use_connection(struct ipc_server_thread_data *server_thread_data) return ret; } +static void wait_for_startup_barrier(struct ipc_server_data *server_data) +{ + /* + * Temporarily hold the startup_barrier mutex before starting, + * which lets us know that it's OK to start serving requests. + */ + pthread_mutex_lock(&server_data->startup_barrier); + pthread_mutex_unlock(&server_data->startup_barrier); +} + /* * Thread proc for an IPC server worker thread. It handles a series of * connections from clients. It cleans and reuses the hPipe between each @@ -550,6 +563,8 @@ static void *server_thread_proc(void *_server_thread_data) memset(&oConnect, 0, sizeof(oConnect)); oConnect.hEvent = hEventConnected; + wait_for_startup_barrier(server_thread_data->server_data); + for (;;) { cr = wait_for_connection(server_thread_data, &oConnect); @@ -752,10 +767,10 @@ static HANDLE create_new_pipe(wchar_t *wpath, int is_first) return hPipe; } -int ipc_server_run_async(struct ipc_server_data **returned_server_data, - const char *path, const struct ipc_server_opts *opts, - ipc_server_application_cb *application_cb, - void *application_data) +int ipc_server_init_async(struct ipc_server_data **returned_server_data, + const char *path, const struct ipc_server_opts *opts, + ipc_server_application_cb *application_cb, + void *application_data) { struct ipc_server_data *server_data; wchar_t wpath[MAX_PATH]; @@ -787,6 +802,13 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, strbuf_addstr(&server_data->buf_path, path); wcscpy(server_data->wpath, wpath); + /* + * Hold the startup_barrier lock so that no threads will progress + * until ipc_server_start_async() is called. + */ + pthread_mutex_init(&server_data->startup_barrier, NULL); + pthread_mutex_lock(&server_data->startup_barrier); + if (nr_threads < 1) nr_threads = 1; @@ -837,6 +859,15 @@ int ipc_server_run_async(struct ipc_server_data **returned_server_data, return 0; } +void ipc_server_start_async(struct ipc_server_data *server_data) +{ + if (!server_data || server_data->started) + return; + + server_data->started = 1; + pthread_mutex_unlock(&server_data->startup_barrier); +} + int ipc_server_stop_async(struct ipc_server_data *server_data) { if (!server_data) @@ -850,6 +881,13 @@ int ipc_server_stop_async(struct ipc_server_data *server_data) * We DO NOT attempt to force them to drop an active connection. */ SetEvent(server_data->hEventStopRequested); + + /* + * If we haven't yet told the threads they are allowed to run, + * do so now, so they can receive the shutdown event. + */ + ipc_server_start_async(server_data); + return 0; } @@ -900,5 +938,7 @@ void ipc_server_free(struct ipc_server_data *server_data) free(std); } + pthread_mutex_destroy(&server_data->startup_barrier); + free(server_data); } diff --git a/compat/stub/procinfo.c b/compat/stub/procinfo.c index 12c0a23c9e..3168cd5714 100644 --- a/compat/stub/procinfo.c +++ b/compat/stub/procinfo.c @@ -6,6 +6,6 @@ * Stub. See sample implementations in compat/linux/procinfo.c and * compat/win32/trace2_win32_process_info.c. */ -void trace2_collect_process_info(enum trace2_process_info_reason reason) +void trace2_collect_process_info(enum trace2_process_info_reason reason UNUSED) { } diff --git a/compat/terminal.c b/compat/terminal.c index 0afda730f2..d54efa1c5d 100644 --- a/compat/terminal.c +++ b/compat/terminal.c @@ -594,7 +594,7 @@ void restore_term(void) { } -char *git_terminal_prompt(const char *prompt, int echo) +char *git_terminal_prompt(const char *prompt, int echo UNUSED) { return getpass(prompt); } diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h index 3a959d124c..a261a925b7 100644 --- a/compat/vcbuild/include/unistd.h +++ b/compat/vcbuild/include/unistd.h @@ -14,7 +14,11 @@ typedef _mode_t mode_t; #ifndef _SSIZE_T_ #define _SSIZE_T_ +#ifdef _WIN64 +typedef __int64 _ssize_t; +#else typedef long _ssize_t; +#endif /* _WIN64 */ #ifndef _OFF_T_ #define _OFF_T_ diff --git a/compat/win32/headless.c b/compat/win32/headless.c index 8b00dfe3bd..11392a0b9a 100644 --- a/compat/win32/headless.c +++ b/compat/win32/headless.c @@ -11,6 +11,8 @@ #include <stdlib.h> #include <wchar.h> +#pragma GCC diagnostic ignored "-Wunused-parameter" + /* * If `dir` contains the path to a Git exec directory, extend `PATH` to * include the corresponding `bin/` directory (which is where all those diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c index b658ca3f81..966ef779b9 100644 --- a/compat/win32/path-utils.c +++ b/compat/win32/path-utils.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "../../git-compat-util.h" #include "../../environment.h" diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c index 85f8f7920c..58980a529c 100644 --- a/compat/win32/pthread.c +++ b/compat/win32/pthread.c @@ -21,7 +21,7 @@ static unsigned __stdcall win32_start_routine(void *arg) return 0; } -int pthread_create(pthread_t *thread, const void *unused, +int pthread_create(pthread_t *thread, const void *attr UNUSED, void *(*start_routine)(void *), void *arg) { thread->arg = arg; diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index cc3221cb2c..e2b5c4f64c 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -18,7 +18,7 @@ */ #define pthread_mutex_t CRITICAL_SECTION -static inline int return_0(int i) { +static inline int return_0(int i UNUSED) { return 0; } #define pthread_mutex_init(a,b) return_0((InitializeCriticalSection((a)), 0)) @@ -70,7 +70,7 @@ static inline void NORETURN pthread_exit(void *ret) } typedef DWORD pthread_key_t; -static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value)) +static inline int pthread_key_create(pthread_key_t *keyp, void (*destructor)(void *value) UNUSED) { return (*keyp = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0; } diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c index 0af18d8882..4e4794743a 100644 --- a/compat/win32/syslog.c +++ b/compat/win32/syslog.c @@ -2,7 +2,7 @@ static HANDLE ms_eventlog; -void openlog(const char *ident, int logopt, int facility) +void openlog(const char *ident, int logopt UNUSED, int facility UNUSED) { if (ms_eventlog) return; diff --git a/compat/win32mmap.c b/compat/win32mmap.c index 519d51f2b6..a4ab4cb939 100644 --- a/compat/win32mmap.c +++ b/compat/win32mmap.c @@ -40,7 +40,7 @@ void *git_mmap(void *start, size_t length, int prot, int flags, int fd, off_t of return MAP_FAILED; } -int git_munmap(void *start, size_t length) +int git_munmap(void *start, size_t length UNUSED) { return !UnmapViewOfFile(start); } diff --git a/compat/winansi.c b/compat/winansi.c index 575813bde8..1b3f916b9f 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -340,7 +340,7 @@ enum { TEXT = 0, ESCAPE = 033, BRACKET = '[' }; -static DWORD WINAPI console_thread(LPVOID unused) +static DWORD WINAPI console_thread(LPVOID data UNUSED) { unsigned char buffer[BUFFER_SIZE]; DWORD bytes; |
