/* * Close the sockets, shutdown the server and exit. * Does not return. * */ static void server_shutdown(struct nsd *nsd) { size_t i; close_all_sockets(nsd->udp, nsd->ifs); close_all_sockets(nsd->tcp, nsd->ifs); /* CHILD: close command channel to parent */ if(nsd->this_child && nsd->this_child->parent_fd != -1) { close(nsd->this_child->parent_fd); nsd->this_child->parent_fd = -1; } /* SERVER: close command channels to children */ if(!nsd->this_child) { for(i=0; i < nsd->child_count; ++i) if(nsd->children[i].child_fd != -1) { close(nsd->children[i].child_fd); nsd->children[i].child_fd = -1; } } log_finalize(); tsig_finalize(); nsd_options_destroy(nsd->options); region_destroy(nsd->region); exit(0); }
// TODO: BUG: The Peak on Windows rarely doesn't close the input thread. // This causes the UI thread to hang on exit. void *input_thread(void *_t, struct dll_io_bridge * _io_bridge) { i_bridge = _io_bridge; atransport *t = (atransport *)_t; apacket *p; int active = 0; D("%s: starting transport input thread, reading from fd %d\n", t->serial, t->fd); for(;;){ if(read_packet(t->fd, t->serial, &p)) { D("%s: failed to read apacket from transport on fd %d\n", t->serial, t->fd ); break; } if(p->msg.command == A_SYNC){ if(p->msg.arg0 == 0) { D("%s: transport SYNC offline\n", t->serial); put_apacket(p); break; } else { if(p->msg.arg1 == t->sync_token) { D("%s: transport SYNC online\n", t->serial); active = 1; } else { D("%s: transport ignoring SYNC %d != %d\n", t->serial, p->msg.arg1, t->sync_token); } } } else { if(active) { D("%s: transport got packet %d, sending to remote\n", t->serial, p->msg.command); t->write_to_remote(p, t); } else { D("%s: transport ignoring packet while offline\n", t->serial); } } put_apacket(p); } // this is necessary to avoid a race condition that occured when a transport closes // while a client socket is still active. D("Pre-close sockets input-thread\n"); close_all_sockets(t); D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd); #ifdef WIN32 kick_transport(t, i_bridge->AdbCloseHandle); #else kick_transport(t, NULL); #endif D("Post-kick transport input-thread\n"); transport_unref(t); D("Post-unref transport input-thread\n"); return 0; }
/* nap_exit: cleans up and leaves */ void nap_exit (int really_quit, char *reason, char *format, ...) { if (dead == 1) { kill_all_threads(); exit(1); } else if (dead == 2) { kill_all_threads(); _exit(1); } else if (dead == 3) { kill_all_threads(); kill(getpid(), SIGKILL); } dead++; set_lastlog_size(NULL, NULL, 0); set_history_size(NULL, NULL, 0); if (really_quit) { kill_all_threads(); say("Signon time : %s", my_ctime(start_time)); say("Signoff time : %s", my_ctime(now)); say("Total uptime : %s", convert_time(now - start_time)); } do_hook(EXIT_LIST, "%s", reason ? reason : empty_string); if (reason) say("%s", reason); close_all_servers(); close_all_sockets(); if (term_initialized) { cursor_to_input(); term_cr(); term_clear_to_eol(); term_reset(); } remove_bindings(); clear_variables(); delete_all_windows(); destroy_call_stack(); write_unfinished_list(); debug_cleanup(); fprintf(stdout, "\r"); fflush(stdout); if (really_quit) exit(0); kill_all_threads(); my_signal(SIGABRT, SIG_DFL, 0); kill(getpid(), SIGABRT); kill(getpid(), SIGQUIT); exit(1); }
static void *input_thread(void *_t) { atransport *t = reinterpret_cast<atransport*>(_t); apacket *p; int active = 0; ADB_LOGD(ADB_TSPT, "%s: starting transport input thread, reading from fd %d", t->serial, t->fd); for (;;) { if (read_packet(t->fd, t->serial, &p)) { ADB_LOGE(ADB_TSPT, "%s: failed to read apacket from transport on fd %d", t->serial, t->fd); break; } if (p->msg.command == A_SYNC) { if (p->msg.arg0 == 0) { ADB_LOGE(ADB_TSPT, "%s: transport SYNC offline", t->serial); put_apacket(p); break; } else { if (p->msg.arg1 == t->sync_token) { ADB_LOGD(ADB_TSPT, "%s: transport SYNC online", t->serial); active = 1; } else { ADB_LOGD(ADB_TSPT, "%s: transport ignoring SYNC %d != %d", t->serial, p->msg.arg1, t->sync_token); } } } else { if (active) { ADB_LOGD(ADB_TSPT, "%s: transport got packet, sending to remote", t->serial); t->write_to_remote(p, t); } else { ADB_LOGD(ADB_TSPT, "%s: transport ignoring packet while offline", t->serial); } } put_apacket(p); } // this is necessary to avoid a race condition that occured when a transport closes // while a client socket is still active. close_all_sockets(t); ADB_LOGD(ADB_TSPT, "%s: transport input thread is exiting, fd %d", t->serial, t->fd); kick_transport(t); transport_unref(t); return 0; }
void handle_offline(atransport *t) { D("adb: offline"); //Close the associated usb t->online = 0; // This is necessary to avoid a race condition that occurred when a transport closes // while a client socket is still active. close_all_sockets(t); t->RunDisconnects(); }
static void *input_thread(void *_t) { atransport *t = _t; apacket *p; int active = 0; D("to_remote: starting input_thread for %p, reading from fd %d\n", t, t->fd); for(;;){ if(read_packet(t->fd, &p)) { D("to_remote: failed to read apacket from transport %p on fd %d\n", t, t->fd ); break; } if(p->msg.command == A_SYNC){ if(p->msg.arg0 == 0) { D("to_remote: transport %p SYNC offline\n", t); put_apacket(p); break; } else { if(p->msg.arg1 == t->sync_token) { D("to_remote: transport %p SYNC online\n", t); active = 1; } else { D("to_remote: trandport %p ignoring SYNC %d != %d\n", t, p->msg.arg1, t->sync_token); } } } else { if(active) { D("to_remote: transport %p got packet, sending to remote\n", t); t->write_to_remote(p, t); } else { D("to_remote: transport %p ignoring packet while offline\n", t); } } put_apacket(p); } // this is necessary to avoid a race condition that occured when a transport closes // while a client socket is still active. close_all_sockets(t); D("to_remote: thread is exiting for transport %p, fd %d\n", t, t->fd); kick_transport(t); transport_unref(t); return 0; }
void state_free(struct state *state) { /* We have to stop the system call thread first, since it's using * sockets that we want to close and reset. */ syscalls_free(state, state->syscalls); /* Then we close the sockets and reset the connections, while * we still have a netdev for injecting reset packets to free * per-connection kernel state. */ close_all_sockets(state); netdev_free(state->netdev); packets_free(state->packets); code_free(state->code); run_unlock(state); if (pthread_mutex_destroy(&state->mutex) != 0) die_perror("pthread_mutex_destroy"); memset(state, 0, sizeof(*state)); /* paranoia to help catch bugs */ free(state); }
/* * Serve DNS requests. */ void server_child(struct nsd *nsd) { size_t i; region_type *server_region = region_create(xalloc, free); netio_type *netio = netio_create(server_region); netio_handler_type *tcp_accept_handlers; query_type *udp_query; sig_atomic_t mode; assert(nsd->server_kind != NSD_SERVER_MAIN); DEBUG(DEBUG_IPC, 2, (LOG_INFO, "child process started")); if (!(nsd->server_kind & NSD_SERVER_TCP)) { close_all_sockets(nsd->tcp, nsd->ifs); } if (!(nsd->server_kind & NSD_SERVER_UDP)) { close_all_sockets(nsd->udp, nsd->ifs); } if (nsd->this_child && nsd->this_child->parent_fd != -1) { netio_handler_type *handler; handler = (netio_handler_type *) region_alloc( server_region, sizeof(netio_handler_type)); handler->fd = nsd->this_child->parent_fd; handler->timeout = NULL; handler->user_data = (struct ipc_handler_conn_data*)region_alloc( server_region, sizeof(struct ipc_handler_conn_data)); ((struct ipc_handler_conn_data*)handler->user_data)->nsd = nsd; ((struct ipc_handler_conn_data*)handler->user_data)->conn = xfrd_tcp_create(server_region); handler->event_types = NETIO_EVENT_READ; handler->event_handler = child_handle_parent_command; netio_add_handler(netio, handler); } if (nsd->server_kind & NSD_SERVER_UDP) { udp_query = query_create(server_region, compressed_dname_offsets, compression_table_size); for (i = 0; i < nsd->ifs; ++i) { struct udp_handler_data *data; netio_handler_type *handler; data = (struct udp_handler_data *) region_alloc( server_region, sizeof(struct udp_handler_data)); data->query = udp_query; data->nsd = nsd; data->socket = &nsd->udp[i]; handler = (netio_handler_type *) region_alloc( server_region, sizeof(netio_handler_type)); handler->fd = nsd->udp[i].s; handler->timeout = NULL; handler->user_data = data; handler->event_types = NETIO_EVENT_READ; handler->event_handler = handle_udp; netio_add_handler(netio, handler); } } /* * Keep track of all the TCP accept handlers so we can enable * and disable them based on the current number of active TCP * connections. */ tcp_accept_handlers = (netio_handler_type *) region_alloc( server_region, nsd->ifs * sizeof(netio_handler_type)); if (nsd->server_kind & NSD_SERVER_TCP) { for (i = 0; i < nsd->ifs; ++i) { struct tcp_accept_handler_data *data; netio_handler_type *handler; data = (struct tcp_accept_handler_data *) region_alloc( server_region, sizeof(struct tcp_accept_handler_data)); data->nsd = nsd; data->socket = &nsd->tcp[i]; data->tcp_accept_handler_count = nsd->ifs; data->tcp_accept_handlers = tcp_accept_handlers; handler = &tcp_accept_handlers[i]; handler->fd = nsd->tcp[i].s; handler->timeout = NULL; handler->user_data = data; handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_ACCEPT; handler->event_handler = handle_tcp_accept; netio_add_handler(netio, handler); } } /* The main loop... */ while ((mode = nsd->mode) != NSD_QUIT) { if(mode == NSD_RUN) nsd->mode = mode = server_signal_mode(nsd); /* Do we need to do the statistics... */ if (mode == NSD_STATS) { #ifdef BIND8_STATS /* Dump the statistics */ bind8_stats(nsd); #else /* !BIND8_STATS */ log_msg(LOG_NOTICE, "Statistics support not enabled at compile time."); #endif /* BIND8_STATS */ nsd->mode = NSD_RUN; } else if (mode == NSD_REAP_CHILDREN) { /* got signal, notify parent. parent reaps terminated children. */ if (nsd->this_child->parent_fd != -1) { sig_atomic_t parent_notify = NSD_REAP_CHILDREN; if (write(nsd->this_child->parent_fd, &parent_notify, sizeof(parent_notify)) == -1) { log_msg(LOG_ERR, "problems sending command from %d to parent: %s", (int) nsd->this_child->pid, strerror(errno)); } } else /* no parent, so reap 'em */ while (waitpid(0, NULL, WNOHANG) > 0) ; nsd->mode = NSD_RUN; } else if(mode == NSD_RUN) { /* Wait for a query... */ if (netio_dispatch(netio, NULL, NULL) == -1) { if (errno != EINTR) { log_msg(LOG_ERR, "netio_dispatch failed: %s", strerror(errno)); break; } } } else if(mode == NSD_QUIT) { /* ignore here, quit */ } else { log_msg(LOG_ERR, "mode bad value %d, back to service.", mode); nsd->mode = NSD_RUN; } } #ifdef BIND8_STATS bind8_stats(nsd); #endif /* BIND8_STATS */ namedb_fd_close(nsd->db); region_destroy(server_region); server_shutdown(nsd); }
void signal_handler(int signal_number) { if (state != NULL) close_all_sockets(state); die("Handled signal %d\n", signal_number); }