Windows: Implement asynchronous functions as threads.
In upload-pack we must explicitly close the output channel of rev-list. (On Unix, the channel is closed automatically because process that runs rev-list terminates.) Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>maint
							parent
							
								
									be501813d2
								
							
						
					
					
						commit
						618ebe9ff9
					
				|  | @ -288,13 +288,23 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const | ||||||
| 	return run_command(&cmd); | 	return run_command(&cmd); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifdef __MINGW32__ | ||||||
|  | static __stdcall unsigned run_thread(void *data) | ||||||
|  | { | ||||||
|  | 	struct async *async = data; | ||||||
|  | 	return async->proc(async->fd_for_proc, async->data); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| int start_async(struct async *async) | int start_async(struct async *async) | ||||||
| { | { | ||||||
| 	int pipe_out[2]; | 	int pipe_out[2]; | ||||||
|  |  | ||||||
| 	if (pipe(pipe_out) < 0) | 	if (pipe(pipe_out) < 0) | ||||||
| 		return error("cannot create pipe: %s", strerror(errno)); | 		return error("cannot create pipe: %s", strerror(errno)); | ||||||
|  | 	async->out = pipe_out[0]; | ||||||
|  |  | ||||||
|  | #ifndef __MINGW32__ | ||||||
| 	async->pid = fork(); | 	async->pid = fork(); | ||||||
| 	if (async->pid < 0) { | 	if (async->pid < 0) { | ||||||
| 		error("fork (async) failed: %s", strerror(errno)); | 		error("fork (async) failed: %s", strerror(errno)); | ||||||
|  | @ -305,16 +315,33 @@ int start_async(struct async *async) | ||||||
| 		close(pipe_out[0]); | 		close(pipe_out[0]); | ||||||
| 		exit(!!async->proc(pipe_out[1], async->data)); | 		exit(!!async->proc(pipe_out[1], async->data)); | ||||||
| 	} | 	} | ||||||
| 	async->out = pipe_out[0]; |  | ||||||
| 	close(pipe_out[1]); | 	close(pipe_out[1]); | ||||||
|  | #else | ||||||
|  | 	async->fd_for_proc = pipe_out[1]; | ||||||
|  | 	async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL); | ||||||
|  | 	if (!async->tid) { | ||||||
|  | 		error("cannot create thread: %s", strerror(errno)); | ||||||
|  | 		close_pair(pipe_out); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int finish_async(struct async *async) | int finish_async(struct async *async) | ||||||
| { | { | ||||||
|  | #ifndef __MINGW32__ | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
|  |  | ||||||
| 	if (wait_or_whine(async->pid)) | 	if (wait_or_whine(async->pid)) | ||||||
| 		ret = error("waitpid (async) failed"); | 		ret = error("waitpid (async) failed"); | ||||||
|  | #else | ||||||
|  | 	DWORD ret = 0; | ||||||
|  | 	if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0) | ||||||
|  | 		ret = error("waiting for thread failed: %lu", GetLastError()); | ||||||
|  | 	else if (!GetExitCodeThread(async->tid, &ret)) | ||||||
|  | 		ret = error("cannot get thread exit code: %lu", GetLastError()); | ||||||
|  | 	CloseHandle(async->tid); | ||||||
|  | #endif | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -76,7 +76,12 @@ struct async { | ||||||
| 	int (*proc)(int fd, void *data); | 	int (*proc)(int fd, void *data); | ||||||
| 	void *data; | 	void *data; | ||||||
| 	int out;	/* caller reads from here and closes it */ | 	int out;	/* caller reads from here and closes it */ | ||||||
|  | #ifndef __MINGW32__ | ||||||
| 	pid_t pid; | 	pid_t pid; | ||||||
|  | #else | ||||||
|  | 	HANDLE tid; | ||||||
|  | 	int fd_for_proc; | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| int start_async(struct async *async); | int start_async(struct async *async); | ||||||
|  |  | ||||||
|  | @ -135,6 +135,8 @@ static int do_rev_list(int fd, void *create_full_pack) | ||||||
| 		die("revision walk setup failed"); | 		die("revision walk setup failed"); | ||||||
| 	mark_edges_uninteresting(revs.commits, &revs, show_edge); | 	mark_edges_uninteresting(revs.commits, &revs, show_edge); | ||||||
| 	traverse_commit_list(&revs, show_commit, show_object); | 	traverse_commit_list(&revs, show_commit, show_object); | ||||||
|  | 	fflush(pack_pipe); | ||||||
|  | 	fclose(pack_pipe); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Johannes Sixt
						Johannes Sixt