void init_transport_registration(void) { int s[2]; if (adb_socketpair(s)) { fatal_errno("cannot open transport registration socketpair"); } transport_registration_send = s[0]; transport_registration_recv = s[1]; fdevent_install(&transport_registration_fde, transport_registration_recv, transport_registration_func, 0); fdevent_set(&transport_registration_fde, FDE_READ); }
static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) { D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); #if defined(_WIN32) fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); return -1; #else // 0 is parent socket, 1 is child socket int sv[2]; if (adb_socketpair(sv) < 0) { printf("[ cannot create socket pair - %s ]\n", strerror(errno)); return -1; } D("socketpair: (%d,%d)", sv[0], sv[1]); *pid = fork(); if (*pid < 0) { printf("- fork failed: %s -\n", strerror(errno)); adb_close(sv[0]); adb_close(sv[1]); return -1; } if (*pid == 0) { adb_close(sv[0]); init_subproc_child(); dup2(sv[1], STDIN_FILENO); dup2(sv[1], STDOUT_FILENO); dup2(sv[1], STDERR_FILENO); adb_close(sv[1]); execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { adb_close(sv[1]); return sv[0]; } #endif /* !defined(_WIN32) */ }
// This test checks when a local socket doesn't enable FDE_READ/FDE_WRITE/FDE_ERROR, it // can still be closed when some error happens on its file handler. // This test successes on linux but fails on mac because of different implementation of // poll(). I think the function tested here is useful to make adb server more stable on // linux. TEST_F(LocalSocketTest, close_with_no_events_installed) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); CloseNoEventsArg arg; arg.socket_fd = socket_fd[1]; pthread_t thread; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(CloseNoEventsThreadFunc), &arg)); // Wait until the fdevent_loop() starts. sleep(1); ASSERT_EQ(2u, fdevent_installed_count()); ASSERT_EQ(0, adb_close(socket_fd[0])); // Wait until the socket is closed. sleep(1); ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); }
int create_jdwp_connection_fd(int pid) { JdwpProcess* proc = _jdwp_list.next; D("looking for pid %d in JDWP process list\n", pid); for ( ; proc != &_jdwp_list; proc = proc->next ) { if (proc->pid == pid) { goto FoundIt; } } D("search failed !!\n"); return -1; FoundIt: { int fds[2]; if (proc->out_count >= MAX_OUT_FDS) { D("%s: too many pending JDWP connection for pid %d\n", __FUNCTION__, pid); return -1; } if (adb_socketpair(fds) < 0) { D("%s: socket pair creation failed: %s\n", __FUNCTION__, strerror(errno)); return -1; } D("socketpair: (%d,%d)", fds[0], fds[1]); proc->out_fds[ proc->out_count ] = fds[1]; if (++proc->out_count == 1) fdevent_add( proc->fde, FDE_WRITE ); return fds[0]; } }
unique_fd create_jdwp_connection_fd(int pid) { D("looking for pid %d in JDWP process list", pid); for (auto& proc : _jdwp_list) { if (proc->pid == pid) { int fds[2]; if (adb_socketpair(fds) < 0) { D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno)); return unique_fd{}; } D("socketpair: (%d,%d)", fds[0], fds[1]); proc->out_fds.emplace_back(fds[1]); if (proc->out_fds.size() == 1) { fdevent_add(proc->fde, FDE_WRITE); } return unique_fd{fds[0]}; } } D("search failed !!"); return unique_fd{}; }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg * m = addTMessage(); int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, m)) { fatal_errno("cannot read transport registration socket"); } t = m->transport; if(m->action == 0){ D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != CS_NOPERM) { // adb_thread_t * output_thread_ptr = (adb_thread_t*)malloc(sizeof(adb_thread_t)); // adb_thread_t * input_thread_ptr = (adb_thread_t*)malloc(sizeof(adb_thread_t)); /* initial references are the two threads */ t->ref_count = 2; if(adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); struct msg { atransport * t; }; struct msg m = { t }; send_js_msg("spawn-io-threads", &m); /*char i_tag[1024]; char o_tag[1024]; sprintf(i_tag, "I: %s_%d", t->serial, get_guid()); sprintf(o_tag, "O: %s_%d", t->serial, get_guid());*/ //dump_thread_tag(); /*if(adb_thread_create(input_thread_ptr, input_thread, t, i_tag)){ fatal_errno("cannot create input thread"); } if(adb_thread_create(output_thread_ptr, output_thread, t, o_tag)){ fatal_errno("cannot create output thread"); }*/ } /* put us on the master device list */ adb_mutex_lock(&transport_lock); t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; update_transports(); }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg m; adb_thread_t output_thread_ptr; adb_thread_t input_thread_ptr; int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, &m)) { fatal_errno("cannot read transport registration socket"); } t = m.transport; //action0 ÒƳý action1 ²åÈë if(m.action == 0) { D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); t->next->prev = t->prev; t->prev->next = t->next; adb_mutex_unlock(&transport_lock); run_transport_disconnects(t); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); memset(t,0xee,sizeof(atransport)); free(t); update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != CS_NOPERM) { /* initial references are the two threads */ t->ref_count = 2; if(adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); if(adb_thread_create(&input_thread_ptr, input_thread, t)){ fatal_errno("cannot create input thread"); } if(adb_thread_create(&output_thread_ptr, output_thread, t)){ fatal_errno("cannot create output thread"); } } adb_mutex_lock(&transport_lock); /* remove from pending list */ t->next->prev = t->prev; t->prev->next = t->next; /* put us on the master device list */ t->next = &transport_list; t->prev = transport_list.prev; t->next->prev = t; t->prev->next = t; adb_mutex_unlock(&transport_lock); t->disconnects.next = t->disconnects.prev = &t->disconnects; update_transports(); }
static void transport_registration_func(int _fd, unsigned ev, void *data) { tmsg m; int s[2]; atransport *t; if(!(ev & FDE_READ)) { return; } if(transport_read_action(_fd, &m)) { fatal_errno("cannot read transport registration socket"); } t = m.transport; if (m.action == 0) { D("transport: %s removing and free'ing %d", t->serial, t->transport_socket); /* IMPORTANT: the remove closes one half of the ** socket pair. The close closes the other half. */ fdevent_remove(&(t->transport_fde)); adb_close(t->fd); adb_mutex_lock(&transport_lock); transport_list.remove(t); adb_mutex_unlock(&transport_lock); if (t->product) free(t->product); if (t->serial) free(t->serial); if (t->model) free(t->model); if (t->device) free(t->device); if (t->devpath) free(t->devpath); delete t; update_transports(); return; } /* don't create transport threads for inaccessible devices */ if (t->connection_state != kCsNoPerm) { /* initial references are the two threads */ t->ref_count = 2; if (adb_socketpair(s)) { fatal_errno("cannot open transport socketpair"); } D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]); t->transport_socket = s[0]; t->fd = s[1]; fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t); fdevent_set(&(t->transport_fde), FDE_READ); if (!adb_thread_create(write_transport_thread, t)) { fatal_errno("cannot create write_transport thread"); } if (!adb_thread_create(read_transport_thread, t)) { fatal_errno("cannot create read_transport thread"); } } adb_mutex_lock(&transport_lock); pending_list.remove(t); transport_list.push_front(t); adb_mutex_unlock(&transport_lock); update_transports(); }
void SetUp() override { ASSERT_EQ(0, adb_socketpair(fds)) << strerror(errno); }
DLL_EXPORT void socket_pipe(int sv[2]) { adb_socketpair(sv); }
void BM_Connection_Echo(benchmark::State& state) { int fds[2]; if (adb_socketpair(fds) != 0) { LOG(FATAL) << "failed to create socketpair"; } auto client = MakeConnection<ConnectionType>(unique_fd(fds[0])); auto server = MakeConnection<ConnectionType>(unique_fd(fds[1])); std::atomic<size_t> received_bytes; fdevent_reset(); std::thread fdevent_thread([]() { fdevent_loop(); }); client->SetReadCallback([&received_bytes](Connection*, std::unique_ptr<apacket> packet) -> bool { received_bytes += packet->payload.size(); return true; }); static const auto handle_packet = [](Connection* connection, std::unique_ptr<apacket> packet) { connection->Write(std::move(packet)); }; server->SetReadCallback([](Connection* connection, std::unique_ptr<apacket> packet) -> bool { if (Policy == ThreadPolicy::MainThread) { auto raw_packet = packet.release(); fdevent_run_on_main_thread([connection, raw_packet]() { std::unique_ptr<apacket> packet(raw_packet); handle_packet(connection, std::move(packet)); }); } else { handle_packet(connection, std::move(packet)); } return true; }); client->SetErrorCallback( [](Connection*, const std::string& error) { LOG(INFO) << "client closed: " << error; }); server->SetErrorCallback( [](Connection*, const std::string& error) { LOG(INFO) << "server closed: " << error; }); client->Start(); server->Start(); for (auto _ : state) { size_t data_size = state.range(0); std::unique_ptr<apacket> packet = std::make_unique<apacket>(); memset(&packet->msg, 0, sizeof(packet->msg)); packet->msg.command = A_WRTE; packet->msg.data_length = data_size; packet->payload.resize(data_size); memset(&packet->payload[0], 0xff, data_size); received_bytes = 0; client->Write(std::move(packet)); while (received_bytes < data_size) { continue; } } state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0)); client->Stop(); server->Stop(); // TODO: Make it so that you don't need to poke the fdevent loop to make it terminate? fdevent_terminate_loop(); fdevent_run_on_main_thread([]() {}); fdevent_thread.join(); }