static int restore_untracked(struct object_id *u_tree) { int res; struct child_process cp = CHILD_PROCESS_INIT; /* * We need to run restore files from a given index, but without * affecting the current index, so we use GIT_INDEX_FILE with * run_command to fork processes that will not interfere. */ cp.git_cmd = 1; argv_array_push(&cp.args, "read-tree"); argv_array_push(&cp.args, oid_to_hex(u_tree)); argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); if (run_command(&cp)) { remove_path(stash_index_path.buf); return -1; } child_process_init(&cp); cp.git_cmd = 1; argv_array_pushl(&cp.args, "checkout-index", "--all", NULL); argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", stash_index_path.buf); res = run_command(&cp); remove_path(stash_index_path.buf); return res; }
static struct child_process *git_proxy_connect(int fd[2], char *host) { const char *port = STR(DEFAULT_GIT_PORT); struct child_process *proxy; get_host_and_port(&host, &port); if (looks_like_command_line_option(host)) die("strange hostname '%s' blocked", host); if (looks_like_command_line_option(port)) die("strange port '%s' blocked", port); proxy = xmalloc(sizeof(*proxy)); child_process_init(proxy); argv_array_push(&proxy->args, git_proxy_command); argv_array_push(&proxy->args, host); argv_array_push(&proxy->args, port); proxy->in = -1; proxy->out = -1; if (start_command(proxy)) die("cannot start proxy %s", git_proxy_command); fd[0] = proxy->out; /* read from proxy stdout */ fd[1] = proxy->in; /* write to proxy stdin */ return proxy; }
static int clone_submodule(const char *path, const char *gitdir, const char *url, const char *depth, const char *reference, int quiet) { struct child_process cp; child_process_init(&cp); argv_array_push(&cp.args, "clone"); argv_array_push(&cp.args, "--no-checkout"); if (quiet) argv_array_push(&cp.args, "--quiet"); if (depth && *depth) argv_array_pushl(&cp.args, "--depth", depth, NULL); if (reference && *reference) argv_array_pushl(&cp.args, "--reference", reference, NULL); if (gitdir && *gitdir) argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL); argv_array_push(&cp.args, url); argv_array_push(&cp.args, path); cp.git_cmd = 1; cp.env = local_repo_env; cp.no_stdin = 1; return run_command(&cp); }
int run_column_filter(int colopts, const struct column_options *opts) { struct argv_array *argv; if (fd_out != -1) return -1; child_process_init(&column_process); argv = &column_process.args; argv_array_push(argv, "column"); argv_array_pushf(argv, "--raw-mode=%d", colopts); if (opts && opts->width) argv_array_pushf(argv, "--width=%d", opts->width); if (opts && opts->indent) argv_array_pushf(argv, "--indent=%s", opts->indent); if (opts && opts->padding) argv_array_pushf(argv, "--padding=%d", opts->padding); fflush(stdout); column_process.in = -1; column_process.out = dup(1); column_process.git_cmd = 1; if (start_command(&column_process)) return -2; fd_out = dup(1); close(1); dup2(column_process.in, 1); close(column_process.in); return 0; }
static int pp_collect_finished(struct parallel_processes *pp) { int i, code; int n = pp->max_processes; int result = 0; while (pp->nr_processes > 0) { for (i = 0; i < pp->max_processes; i++) if (pp->children[i].state == GIT_CP_WAIT_CLEANUP) break; if (i == pp->max_processes) break; code = finish_command(&pp->children[i].process); code = pp->task_finished(code, &pp->children[i].err, pp->data, &pp->children[i].data); if (code) result = code; if (code < 0) break; pp->nr_processes--; pp->children[i].state = GIT_CP_FREE; pp->pfd[i].fd = -1; child_process_init(&pp->children[i].process); if (i != pp->output_owner) { strbuf_addbuf(&pp->buffered_output, &pp->children[i].err); strbuf_reset(&pp->children[i].err); } else { strbuf_write(&pp->children[i].err, stderr); strbuf_reset(&pp->children[i].err); /* Output all other finished child processes */ strbuf_write(&pp->buffered_output, stderr); strbuf_reset(&pp->buffered_output); /* * Pick next process to output live. * NEEDSWORK: * For now we pick it randomly by doing a round * robin. Later we may want to pick the one with * the most output or the longest or shortest * running process time. */ for (i = 0; i < n; i++) if (pp->children[(pp->output_owner + i) % n].state == GIT_CP_WORKING) break; pp->output_owner = (pp->output_owner + i) % n; } } return result; }
static void pp_init(struct parallel_processes *pp, int n, get_next_task_fn get_next_task, start_failure_fn start_failure, task_finished_fn task_finished, void *data) { int i; if (n < 1) n = online_cpus(); pp->max_processes = n; trace_printf("run_processes_parallel: preparing to run up to %d tasks", n); pp->data = data; if (!get_next_task) die("BUG: you need to specify a get_next_task function"); pp->get_next_task = get_next_task; pp->start_failure = start_failure ? start_failure : default_start_failure; pp->task_finished = task_finished ? task_finished : default_task_finished; pp->nr_processes = 0; pp->output_owner = 0; pp->shutdown = 0; pp->children = xcalloc(n, sizeof(*pp->children)); pp->pfd = xcalloc(n, sizeof(*pp->pfd)); strbuf_init(&pp->buffered_output, 0); for (i = 0; i < n; i++) { strbuf_init(&pp->children[i].err, 0); child_process_init(&pp->children[i].process); pp->pfd[i].events = POLLIN | POLLHUP; pp->pfd[i].fd = -1; } pp_for_signal = pp; sigchain_push_common(handle_children_on_signal); }
int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, const char *cmd, subprocess_start_fn startfn) { int err; struct child_process *process; const char *argv[] = { cmd, NULL }; entry->cmd = cmd; process = &entry->process; child_process_init(process); process->argv = argv; process->use_shell = 1; process->in = -1; process->out = -1; process->clean_on_exit = 1; process->clean_on_exit_handler = subprocess_exit_handler; err = start_command(process); if (err) { error("cannot fork to run subprocess '%s'", cmd); return err; } hashmap_entry_init(entry, strhash(cmd)); err = startfn(entry); if (err) { error("initialization for subprocess '%s' failed", cmd); subprocess_stop(hashmap, entry); return err; } hashmap_add(hashmap, entry); return 0; }
static const char *push_to_deploy(unsigned char *sha1, struct argv_array *env, const char *work_tree) { const char *update_refresh[] = { "update-index", "-q", "--ignore-submodules", "--refresh", NULL }; const char *diff_files[] = { "diff-files", "--quiet", "--ignore-submodules", "--", NULL }; const char *diff_index[] = { "diff-index", "--quiet", "--cached", "--ignore-submodules", NULL, "--", NULL }; const char *read_tree[] = { "read-tree", "-u", "-m", NULL, NULL }; struct child_process child = CHILD_PROCESS_INIT; child.argv = update_refresh; child.env = env->argv; child.dir = work_tree; child.no_stdin = 1; child.stdout_to_stderr = 1; child.git_cmd = 1; if (run_command(&child)) return "Up-to-date check failed"; /* run_command() does not clean up completely; reinitialize */ child_process_init(&child); child.argv = diff_files; child.env = env->argv; child.dir = work_tree; child.no_stdin = 1; child.stdout_to_stderr = 1; child.git_cmd = 1; if (run_command(&child)) return "Working directory has unstaged changes"; /* diff-index with either HEAD or an empty tree */ diff_index[4] = head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX; child_process_init(&child); child.argv = diff_index; child.env = env->argv; child.no_stdin = 1; child.no_stdout = 1; child.stdout_to_stderr = 0; child.git_cmd = 1; if (run_command(&child)) return "Working directory has staged changes"; read_tree[3] = sha1_to_hex(sha1); child_process_init(&child); child.argv = read_tree; child.env = env->argv; child.dir = work_tree; child.no_stdin = 1; child.no_stdout = 1; child.stdout_to_stderr = 0; child.git_cmd = 1; if (run_command(&child)) return "Could not update working tree to new HEAD"; return NULL; }
/* * This returns a dummy child_process if the transport protocol does not * need fork(2), or a struct child_process object if it does. Once done, * finish the connection with finish_connect() with the value returned from * this function (it is safe to call finish_connect() with NULL to support * the former case). * * If it returns, the connect is successful; it just dies on errors (this * will hopefully be changed in a libification effort, to return NULL when * the connection failed). */ struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags) { char *hostandport, *path; struct child_process *conn = &no_fork; enum protocol protocol; struct strbuf cmd = STRBUF_INIT; /* Without this we cannot rely on waitpid() to tell * what happened to our children. */ signal(SIGCHLD, SIG_DFL); protocol = parse_connect_url(url, &hostandport, &path); if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) { printf("Diag: url=%s\n", url ? url : "NULL"); printf("Diag: protocol=%s\n", prot_name(protocol)); printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL"); printf("Diag: path=%s\n", path ? path : "NULL"); conn = NULL; } else if (protocol == PROTO_GIT) { /* * Set up virtual host information based on where we will * connect, unless the user has overridden us in * the environment. */ char *target_host = getenv("GIT_OVERRIDE_VIRTUAL_HOST"); if (target_host) target_host = xstrdup(target_host); else target_host = xstrdup(hostandport); transport_check_allowed("git"); /* These underlying connection commands die() if they * cannot connect. */ if (git_use_proxy(hostandport)) conn = git_proxy_connect(fd, hostandport); else git_tcp_connect(fd, hostandport, flags); /* * Separate original protocol components prog and path * from extended host header with a NUL byte. * * Note: Do not add any other headers here! Doing so * will cause older git-daemon servers to crash. */ packet_write(fd[1], "%s %s%chost=%s%c", prog, path, 0, target_host, 0); free(target_host); } else { conn = xmalloc(sizeof(*conn)); child_process_init(conn); strbuf_addstr(&cmd, prog); strbuf_addch(&cmd, ' '); sq_quote_buf(&cmd, path); conn->in = conn->out = -1; if (protocol == PROTO_SSH) { const char *ssh; int putty, tortoiseplink = 0; char *ssh_host = hostandport; const char *port = NULL; transport_check_allowed("ssh"); get_host_and_port(&ssh_host, &port); if (!port) port = get_port(ssh_host); if (flags & CONNECT_DIAG_URL) { printf("Diag: url=%s\n", url ? url : "NULL"); printf("Diag: protocol=%s\n", prot_name(protocol)); printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL"); printf("Diag: port=%s\n", port ? port : "NONE"); printf("Diag: path=%s\n", path ? path : "NULL"); free(hostandport); free(path); free(conn); return NULL; } ssh = getenv("GIT_SSH_COMMAND"); if (ssh) { conn->use_shell = 1; putty = 0; } else { const char *base; char *ssh_dup; ssh = getenv("GIT_SSH"); if (!ssh) ssh = "ssh"; ssh_dup = xstrdup(ssh); base = basename(ssh_dup); tortoiseplink = !strcasecmp(base, "tortoiseplink") || !strcasecmp(base, "tortoiseplink.exe"); putty = !strcasecmp(base, "plink") || !strcasecmp(base, "plink.exe") || tortoiseplink; free(ssh_dup); } argv_array_push(&conn->args, ssh); if (tortoiseplink) argv_array_push(&conn->args, "-batch"); if (port) { /* P is for PuTTY, p is for OpenSSH */ argv_array_push(&conn->args, putty ? "-P" : "-p"); argv_array_push(&conn->args, port); } argv_array_push(&conn->args, ssh_host); } else { /* remove repo-local variables from the environment */ conn->env = local_repo_env; conn->use_shell = 1; transport_check_allowed("file"); } argv_array_push(&conn->args, cmd.buf); if (start_command(conn)) die("unable to fork"); fd[0] = conn->out; /* read from child's stdout */ fd[1] = conn->in; /* write to child's stdin */ strbuf_release(&cmd); } free(hostandport); free(path); return conn; }
/* * This returns the dummy child_process `no_fork` if the transport protocol * does not need fork(2), or a struct child_process object if it does. Once * done, finish the connection with finish_connect() with the value returned * from this function (it is safe to call finish_connect() with NULL to * support the former case). * * If it returns, the connect is successful; it just dies on errors (this * will hopefully be changed in a libification effort, to return NULL when * the connection failed). */ struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags) { char *hostandport, *path; struct child_process *conn; enum protocol protocol; /* Without this we cannot rely on waitpid() to tell * what happened to our children. */ signal(SIGCHLD, SIG_DFL); protocol = parse_connect_url(url, &hostandport, &path); if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) { printf("Diag: url=%s\n", url ? url : "NULL"); printf("Diag: protocol=%s\n", prot_name(protocol)); printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL"); printf("Diag: path=%s\n", path ? path : "NULL"); conn = NULL; } else if (protocol == PROTO_GIT) { conn = git_connect_git(fd, hostandport, path, prog, flags); } else { struct strbuf cmd = STRBUF_INIT; const char *const *var; conn = xmalloc(sizeof(*conn)); child_process_init(conn); if (looks_like_command_line_option(path)) die("strange pathname '%s' blocked", path); strbuf_addstr(&cmd, prog); strbuf_addch(&cmd, ' '); sq_quote_buf(&cmd, path); /* remove repo-local variables from the environment */ for (var = local_repo_env; *var; var++) argv_array_push(&conn->env_array, *var); conn->use_shell = 1; conn->in = conn->out = -1; if (protocol == PROTO_SSH) { char *ssh_host = hostandport; const char *port = NULL; transport_check_allowed("ssh"); get_host_and_port(&ssh_host, &port); if (!port) port = get_port(ssh_host); if (flags & CONNECT_DIAG_URL) { printf("Diag: url=%s\n", url ? url : "NULL"); printf("Diag: protocol=%s\n", prot_name(protocol)); printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL"); printf("Diag: port=%s\n", port ? port : "NONE"); printf("Diag: path=%s\n", path ? path : "NULL"); free(hostandport); free(path); free(conn); strbuf_release(&cmd); return NULL; } fill_ssh_args(conn, ssh_host, port, flags); } else { transport_check_allowed("file"); if (get_protocol_version_config() > 0) { argv_array_pushf(&conn->env_array, GIT_PROTOCOL_ENVIRONMENT "=version=%d", get_protocol_version_config()); } } argv_array_push(&conn->args, cmd.buf); if (start_command(conn)) die("unable to fork"); fd[0] = conn->out; /* read from child's stdout */ fd[1] = conn->in; /* write to child's stdin */ strbuf_release(&cmd); } free(hostandport); free(path); return conn; }
// * ================================================================================ * // @ main // * ================================================================================ * int main(int argc, char ** argv) { //open the log file pLogFile = &CCLogFile; CCLogFile.startlog(1); CCLogFile.SetLogSize(2*1000*1000); CCLogFile.SetLoglevel(1); CCLogFile.logopen(); if ( myconfig.readfile(CONFIG_FILE_PATH) == 0 ) { printf("appserver: read config file '%s' error\n", CONFIG_FILE_PATH); LOG(LOG1, "appserver: read config file '%s' error\n", CONFIG_FILE_PATH); sleep(2); exit(0); } CCLogFile.SetLoglevel(ToInt(myconfig["LogLevel"][1])); //TANG 2010-9-4 11:02 //处理命令行参数 if ( argc == 3 && strcmp(argv[1], "reload") == 0 && strcmp(argv[2], "config") == 0 ) { send_msg_reload_config("127.0.0.1", (( ToInt(myconfig["AppServerListenPort"][1]) > 0 ) ? ToInt(myconfig["AppServerListenPort"][1]) : 4016)); exit(0); } LOG(LOG1, "appserver: start\n"); child_process_init(SN3_SERVICE_NUMBER); //application_envinit(); //LOG(LOG1, "appserver: application_envinit() done\n"); _appserver_initial(); LOG(LOG1, "appserver: _appserver_initial() done\n"); nthread_create(thread_sockserver, NULL, 64*1024); nthread_create(thread_procdata_sendsmsg, NULL, 64*1024); tcp_server1.SetpLog(&CCLogFile); tcp_server1.SetCallBackFunc(deal_client_msg); if ( ToInt(myconfig["AppServerListenPort"][1]) > 0 ) { tcp_server1.Listen(ToInt(myconfig["AppServerListenPort"][1]), 180); } else { tcp_server1.Listen(4016, 180); } //NPOSITION pos; //rundata_realtest* p_runtest; string s_terminal, s_msg_type; time_t t_check_hb_timeout = time(NULL); time_t t_check_test_timeout = time(NULL); while(g_appserver.m_runing) { child_process_hb(SN3_SERVICE_NUMBER); /* pos = NULL; while(NULL != (p_runtest = realtest_next(pos))) { if ( time(NULL) >= p_runtest->tm_end ) { CClientMsg::ansy_getitem(p_runtest->s_testdata.c_str(), "terminal", s_terminal); CClientMsg::ansy_getitem(p_runtest->s_testdata.c_str(), "msg", s_msg_type); //PESQ的实时测试,ftp扫描单元可能直接修改数据库的测试结果为X CNString sql; sql.Format("select * from BUSSOP where BUSSOP_ID = '%s' and (STATUS != 'X' and STATUS != 'Y');", p_runtest->s_bussopid.c_str()); DATASET dbresult; if ( DB1.db_select(sql.c_str(), dbresult, LOG6) > 0 ) { LOG(LOG1, "测试超时 [%s] '%c', s_bussopid='%s', timeout=%ds\n\n", s_terminal.c_str(), p_runtest->u_buss, p_runtest->s_bussopid.c_str(), p_runtest->tm_end - p_runtest->tm_start ); int i_rescode = 1; if ( dbresult[0]["STATUS"] == "W" ) i_rescode = 5001; appserver_dbupdate_bussop_error(p_runtest->s_bussopid.c_str(), i_rescode); } t_uchar u_buss = p_runtest->u_buss; p_runtest = realtest_next(pos); realtest_delete(s_terminal.c_str(), u_buss); } } */ n_sleep(1000); if ( time(NULL) >= t_check_hb_timeout + 10*60 ) { CNString sql; sql.Format("select * from CONFIG_TERMINAL where TERMINAL_STATE = 0 and HEARTBEAT_STATE = 0 and %u >= T_RECV_HEARTBEAT + %d;", time(NULL), ToInt(myconfig["SMS_HEARTBEAT_TIMEOUT"][1])); DATASET dbresult; if ( DB1.db_select(sql.c_str(), dbresult, LOG6) > 0 ) { //某终端心跳短信超时 for ( int i=0; i<dbresult.size(); i++ ) { string s_terminal = dbresult[i]["TERMINAL_ID"]; string s_bussopid; string s_starttime = time_format_str(time(NULL), 1); _ori_bussopid(s_bussopid, BUSSOPTYPE_ROUTINE, s_terminal.c_str(), "IA", s_starttime.c_str()); appserver_dbinsert_bussop(s_bussopid.c_str(), BUSSOPTYPE_ROUTINE, "IA", s_terminal.c_str(), s_starttime.c_str(), "", 'X'); insert_bussop_exception_result(s_bussopid.c_str(), "HEARTBEAT_TMOUT"); update_terminal_heartbeat_timeout(s_terminal.c_str()); } } t_check_hb_timeout = time(NULL); } if ( time(NULL) >= t_check_test_timeout + 60 ) { DATASET dbresult; CNString sql; sql.Format("SELECT * from BUSSOP where (STATUS != 'X' and STATUS != 'Y') and INIVATE_TYPE = 'T' and '%s' >= TIMEOUT order by STARTTIME;", time_format_str(time(NULL), 1).c_str()); if ( DB1.db_select(sql.c_str(), dbresult, LOG6) > 0 ) { //测试超时 for ( int i=0; i<dbresult.size(); i++ ) { LOG(LOG1, "DB 测试超时 terminal='%s', KQI='%s', s_bussopid='%s', tid='%s', timeout=%ds\n\n", dbresult[i]["TERMINAL_ID"].c_str(), dbresult[i]["KQI_TYPE"].c_str(), dbresult[i]["BUSSOP_ID"].c_str(), dbresult[i]["TID"].c_str(), time_string_to_time_t(dbresult[i]["TIMEOUT"]) - time_string_to_time_t(dbresult[i]["STARTTIME"]) ); int i_rescode = 1; if ( dbresult[i]["STATUS"] == "W" ) i_rescode = 5001; appserver_dbupdate_bussop_error(dbresult[i]["BUSSOP_ID"].c_str(), i_rescode); } } t_check_test_timeout = time(NULL); } } _appserver_destroy(); tcp_server1.Close(); LOG(LOG1, "appserver: exit\n"); return 0; }
static int get_next_submodule(struct child_process *cp, struct strbuf *err, void *data, void **task_cb) { int ret = 0; struct submodule_parallel_fetch *spf = data; for (; spf->count < active_nr; spf->count++) { struct strbuf submodule_path = STRBUF_INIT; struct strbuf submodule_git_dir = STRBUF_INIT; struct strbuf submodule_prefix = STRBUF_INIT; const struct cache_entry *ce = active_cache[spf->count]; const char *git_dir, *default_argv; const struct submodule *submodule; if (!S_ISGITLINK(ce->ce_mode)) continue; submodule = submodule_from_path(null_sha1, ce->name); if (!submodule) submodule = submodule_from_name(null_sha1, ce->name); default_argv = "yes"; if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) { if (submodule && submodule->fetch_recurse != RECURSE_SUBMODULES_NONE) { if (submodule->fetch_recurse == RECURSE_SUBMODULES_OFF) continue; if (submodule->fetch_recurse == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } else { if ((config_fetch_recurse_submodules == RECURSE_SUBMODULES_OFF) || gitmodules_is_unmerged) continue; if (config_fetch_recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } } } else if (spf->command_line_option == RECURSE_SUBMODULES_ON_DEMAND) { if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name)) continue; default_argv = "on-demand"; } strbuf_addf(&submodule_path, "%s/%s", spf->work_tree, ce->name); strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf); strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name); git_dir = read_gitfile(submodule_git_dir.buf); if (!git_dir) git_dir = submodule_git_dir.buf; if (is_directory(git_dir)) { child_process_init(cp); cp->dir = strbuf_detach(&submodule_path, NULL); cp->env = local_repo_env; cp->git_cmd = 1; if (!spf->quiet) strbuf_addf(err, "Fetching submodule %s%s\n", spf->prefix, ce->name); argv_array_init(&cp->args); argv_array_pushv(&cp->args, spf->args.argv); argv_array_push(&cp->args, default_argv); argv_array_push(&cp->args, "--submodule-prefix"); argv_array_push(&cp->args, submodule_prefix.buf); ret = 1; } strbuf_release(&submodule_path); strbuf_release(&submodule_git_dir); strbuf_release(&submodule_prefix); if (ret) { spf->count++; return 1; } } return 0; }