car_timestamp_sender::~car_timestamp_sender() { cleanup_thread(); cleanup_socket(); cleanup_wsa(); timeEndPeriod(1); }
/* destroy a thread when its refcount is 0 */ void destroy_thread(struct object *obj) { struct w32thread *thread = (struct w32thread *)obj; ktrace("%p\n", obj); cleanup_thread(thread); release_object(thread->process); if (thread->token) release_object(thread->token); }
void * main_thread(void * data) { int flag=1,choice,n; int temp; TCPsocket client_socket,server_socket; if(!intialize_thread()) { printf("\n Therer is some error while initializing thread"); return 0; } printf("\n Value of active ports is:%d",get_active_threads()); // first server receive request from client to connect and open master server socket. To be created only once.-permanent if(common_connect_server(&host_ipaddress,&server_socket,global_port,(const char *)NULL)==0) return (void *)1; while(quit) { // Open client socket on server side for sending dynamic port address-temprary if((client_socket=SDLNet_TCP_Accept(server_socket))) { // send port address to client pthread_mutex_lock(&mutex_variable); printf("\n Value of active ports:%d",get_active_threads()); if(get_active_threads()==0) { int temp=0; SDLNet_TCP_Send(client_socket,&(temp),2); SDLNet_TCP_Close(client_socket); pthread_mutex_unlock(&mutex_variable); } else if(SDLNet_TCP_Send(client_socket,&(thread_header->client.port),2)==2) { printf("\nNew Port is send to client"); // close temprary client socket SDLNet_TCP_Close(client_socket); // opening port so that server can accept content from client in different thread; pthread_mutex_unlock(&mutex_variable); printf("\n Activating thread"); activate_thread(); } } } printf("\nEverything is OK now exiting"); SDLNet_TCP_Close(server_socket); cleanup_thread(); return NULL; }
static void cleanup(void) { LOG("Cleaning up . . .\n"); int i = 0; while (i < NUM_SENSORS) { cleanup_thread(i); i++; } LOG("Cleaned!\n"); LOG("** SensorEmulationClientServer - Exited **\n"); putchar('\n'); exit(0); }
void TestThisThread() { hadesmem::Thread thread(::GetCurrentThreadId()); BOOST_TEST_EQ(thread, thread); hadesmem::Thread thread_new(::GetCurrentThreadId()); BOOST_TEST_EQ(thread, thread_new); hadesmem::Thread const thread_moved(std::move(thread_new)); hadesmem::Thread thread_copy(thread); BOOST_TEST_EQ(thread_copy, thread); thread = thread_copy; BOOST_TEST_EQ(thread, thread_copy); thread_new = std::move(thread_copy); BOOST_TEST_EQ(thread, thread_new); BOOST_TEST(thread >= thread); BOOST_TEST(thread <= thread); BOOST_TEST_EQ(thread.GetId(), ::GetCurrentThreadId()); std::stringstream thread_str_1; thread_str_1.imbue(std::locale::classic()); thread_str_1 << thread; DWORD thread_id_1; thread_str_1 >> thread_id_1; BOOST_TEST_EQ(thread.GetId(), thread_id_1); std::wstringstream thread_str_2; thread_str_2.imbue(std::locale::classic()); thread_str_2 << thread; DWORD thread_id_2; thread_str_2 >> thread_id_2; BOOST_TEST_EQ(thread.GetId(), thread_id_2); hadesmem::detail::SmartHandle quit_event( ::CreateEvent(nullptr, TRUE, FALSE, nullptr)); DWORD other_id = 0; hadesmem::detail::SmartHandle wait_thread( ::CreateThread(nullptr, 0, &WaitFunc, &quit_event, 0, &other_id)); // Disgusting hack to work around a potential race condition where we suspend // the thread before it's actually waiting on our event, and instead it's // still in its initialization routine and ends up holding a lock that the // main thread will need (e.g. from malloc). See thread_140224_144550.dmp. ::Sleep(5 * 1000); auto const cleanup_thread_func = [&]() { BOOST_TEST_NE(::SetEvent(quit_event.GetHandle()), 0); BOOST_TEST_EQ(::WaitForSingleObject(wait_thread.GetHandle(), INFINITE), WAIT_OBJECT_0); }; { ScopeExit<decltype(cleanup_thread_func)> cleanup_thread( cleanup_thread_func); hadesmem::Thread const other_thread(other_id); BOOST_TEST_EQ(hadesmem::SuspendThread(other_thread), 0UL); BOOST_TEST_EQ(hadesmem::SuspendThread(other_thread), 1UL); BOOST_TEST_EQ(hadesmem::ResumeThread(other_thread), 2UL); BOOST_TEST_EQ(hadesmem::ResumeThread(other_thread), 1UL); { hadesmem::SuspendedThread const suspend_thread(other_thread.GetId()); CONTEXT const full_context = hadesmem::GetThreadContext(other_thread, CONTEXT_FULL); CONTEXT const all_context = hadesmem::GetThreadContext(other_thread, CONTEXT_ALL); hadesmem::SetThreadContext(other_thread, full_context); hadesmem::SetThreadContext(other_thread, all_context); BOOST_TEST_THROWS(hadesmem::GetThreadContext(thread, CONTEXT_FULL), hadesmem::Error); } { hadesmem::SuspendedProcess const suspend_process(::GetCurrentProcessId()); } } }
void child_main(apr_pool_t *pconf) { apr_status_t status; apr_hash_t *ht; ap_listen_rec *lr; HANDLE child_events[2]; HANDLE *child_handles; int listener_started = 0; int threads_created = 0; int watch_thread; int time_remains; int cld; unsigned tid; int rv; int i; apr_pool_create(&pchild, pconf); apr_pool_tag(pchild, "pchild"); ap_run_child_init(pchild, ap_server_conf); ht = apr_hash_make(pchild); /* Initialize the child_events */ max_requests_per_child_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!max_requests_per_child_event) { ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, "Child %lu: Failed to create a max_requests event.", my_pid); exit(APEXIT_CHILDINIT); } child_events[0] = exit_event; child_events[1] = max_requests_per_child_event; allowed_globals.jobsemaphore = CreateSemaphore(NULL, 0, 1000000, NULL); apr_thread_mutex_create(&allowed_globals.jobmutex, APR_THREAD_MUTEX_DEFAULT, pchild); /* * Wait until we have permission to start accepting connections. * start_mutex is used to ensure that only one child ever * goes into the listen/accept loop at once. */ status = apr_proc_mutex_lock(start_mutex); if (status != APR_SUCCESS) { ap_log_error(APLOG_MARK,APLOG_ERR, status, ap_server_conf, "Child %lu: Failed to acquire the start_mutex. Process will exit.", my_pid); exit(APEXIT_CHILDINIT); } ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Acquired the start mutex.", my_pid); /* * Create the worker thread dispatch IOCompletionPort * on Windows NT/2000 */ if (use_acceptex) { /* Create the worker thread dispatch IOCP */ ThreadDispatchIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); /* CONCURRENT ACTIVE THREADS */ apr_thread_mutex_create(&qlock, APR_THREAD_MUTEX_DEFAULT, pchild); qwait_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!qwait_event) { ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, "Child %lu: Failed to create a qwait event.", my_pid); exit(APEXIT_CHILDINIT); } } /* * Create the pool of worker threads */ ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Starting %d worker threads.", my_pid, ap_threads_per_child); child_handles = (HANDLE) apr_pcalloc(pchild, ap_threads_per_child * sizeof(HANDLE)); apr_thread_mutex_create(&child_lock, APR_THREAD_MUTEX_DEFAULT, pchild); while (1) { for (i = 0; i < ap_threads_per_child; i++) { int *score_idx; int status = ap_scoreboard_image->servers[0][i].status; if (status != SERVER_GRACEFUL && status != SERVER_DEAD) { continue; } ap_update_child_status_from_indexes(0, i, SERVER_STARTING, NULL); child_handles[i] = (HANDLE) _beginthreadex(NULL, (unsigned)ap_thread_stacksize, worker_main, (void *) i, 0, &tid); if (child_handles[i] == 0) { ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, "Child %lu: _beginthreadex failed. Unable to create all worker threads. " "Created %d of the %d threads requested with the ThreadsPerChild configuration directive.", my_pid, threads_created, ap_threads_per_child); ap_signal_parent(SIGNAL_PARENT_SHUTDOWN); goto shutdown; } threads_created++; /* Save the score board index in ht keyed to the thread handle. We need this * when cleaning up threads down below... */ apr_thread_mutex_lock(child_lock); score_idx = apr_pcalloc(pchild, sizeof(int)); *score_idx = i; apr_hash_set(ht, &child_handles[i], sizeof(HANDLE), score_idx); apr_thread_mutex_unlock(child_lock); } /* Start the listener only when workers are available */ if (!listener_started && threads_created) { create_listener_thread(); listener_started = 1; winnt_mpm_state = AP_MPMQ_RUNNING; } if (threads_created == ap_threads_per_child) { break; } /* Check to see if the child has been told to exit */ if (WaitForSingleObject(exit_event, 0) != WAIT_TIMEOUT) { break; } /* wait for previous generation to clean up an entry in the scoreboard */ apr_sleep(1 * APR_USEC_PER_SEC); } /* Wait for one of three events: * exit_event: * The exit_event is signaled by the parent process to notify * the child that it is time to exit. * * max_requests_per_child_event: * This event is signaled by the worker threads to indicate that * the process has handled MaxRequestsPerChild connections. * * TIMEOUT: * To do periodic maintenance on the server (check for thread exits, * number of completion contexts, etc.) * * XXX: thread exits *aren't* being checked. * * XXX: other_child - we need the process handles to the other children * in order to map them to apr_proc_other_child_read (which is not * named well, it's more like a_p_o_c_died.) * * XXX: however - if we get a_p_o_c handle inheritance working, and * the parent process creates other children and passes the pipes * to our worker processes, then we have no business doing such * things in the child_main loop, but should happen in master_main. */ while (1) { #if !APR_HAS_OTHER_CHILD rv = WaitForMultipleObjects(2, (HANDLE *) child_events, FALSE, INFINITE); cld = rv - WAIT_OBJECT_0; #else rv = WaitForMultipleObjects(2, (HANDLE *) child_events, FALSE, 1000); cld = rv - WAIT_OBJECT_0; if (rv == WAIT_TIMEOUT) { apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); } else #endif if (rv == WAIT_FAILED) { /* Something serious is wrong */ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, "Child %lu: WAIT_FAILED -- shutting down server", my_pid); break; } else if (cld == 0) { /* Exit event was signaled */ ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Exit event signaled. Child process is ending.", my_pid); break; } else { /* MaxRequestsPerChild event set by the worker threads. * Signal the parent to restart */ ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Process exiting because it reached " "MaxRequestsPerChild. Signaling the parent to " "restart a new child process.", my_pid); ap_signal_parent(SIGNAL_PARENT_RESTART); break; } } /* * Time to shutdown the child process */ shutdown: winnt_mpm_state = AP_MPMQ_STOPPING; /* Setting is_graceful will cause threads handling keep-alive connections * to close the connection after handling the current request. */ is_graceful = 1; /* Close the listening sockets. Note, we must close the listeners * before closing any accept sockets pending in AcceptEx to prevent * memory leaks in the kernel. */ for (lr = ap_listeners; lr ; lr = lr->next) { apr_socket_close(lr->sd); } /* Shutdown listener threads and pending AcceptEx socksts * but allow the worker threads to continue consuming from * the queue of accepted connections. */ shutdown_in_progress = 1; Sleep(1000); /* Tell the worker threads to exit */ workers_may_exit = 1; /* Release the start_mutex to let the new process (in the restart * scenario) a chance to begin accepting and servicing requests */ rv = apr_proc_mutex_unlock(start_mutex); if (rv == APR_SUCCESS) { ap_log_error(APLOG_MARK,APLOG_NOTICE, rv, ap_server_conf, "Child %lu: Released the start mutex", my_pid); } else { ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf, "Child %lu: Failure releasing the start mutex", my_pid); } /* Shutdown the worker threads */ if (!use_acceptex) { for (i = 0; i < threads_created; i++) { add_job(INVALID_SOCKET); } } else { /* Windows NT/2000 */ /* Post worker threads blocked on the ThreadDispatch IOCompletion port */ while (g_blocked_threads > 0) { ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, ap_server_conf, "Child %lu: %d threads blocked on the completion port", my_pid, g_blocked_threads); for (i=g_blocked_threads; i > 0; i--) { PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_SHUTDOWN, NULL); } Sleep(1000); } /* Empty the accept queue of completion contexts */ apr_thread_mutex_lock(qlock); while (qhead) { CloseHandle(qhead->Overlapped.hEvent); closesocket(qhead->accept_socket); qhead = qhead->next; } apr_thread_mutex_unlock(qlock); } /* Give busy threads a chance to service their connections, * (no more than the global server timeout period which * we track in msec remaining). */ watch_thread = 0; time_remains = (int)(ap_server_conf->timeout / APR_TIME_C(1000)); while (threads_created) { int nFailsafe = MAXIMUM_WAIT_OBJECTS; DWORD dwRet; /* Every time we roll over to wait on the first group * of MAXIMUM_WAIT_OBJECTS threads, take a breather, * and infrequently update the error log. */ if (watch_thread >= threads_created) { if ((time_remains -= 100) < 0) break; /* Every 30 seconds give an update */ if ((time_remains % 30000) == 0) { ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Waiting %d more seconds " "for %d worker threads to finish.", my_pid, time_remains / 1000, threads_created); } /* We'll poll from the top, 10 times per second */ Sleep(100); watch_thread = 0; } /* Fairness, on each iteration we will pick up with the thread * after the one we just removed, even if it's a single thread. * We don't block here. */ dwRet = WaitForMultipleObjects(min(threads_created - watch_thread, MAXIMUM_WAIT_OBJECTS), child_handles + watch_thread, 0, 0); if (dwRet == WAIT_FAILED) { break; } if (dwRet == WAIT_TIMEOUT) { /* none ready */ watch_thread += MAXIMUM_WAIT_OBJECTS; continue; } else if (dwRet >= WAIT_ABANDONED_0) { /* We just got the ownership of the object, which * should happen at most MAXIMUM_WAIT_OBJECTS times. * It does NOT mean that the object is signaled. */ if ((nFailsafe--) < 1) break; } else { watch_thread += (dwRet - WAIT_OBJECT_0); if (watch_thread >= threads_created) break; cleanup_thread(child_handles, &threads_created, watch_thread); } } /* Kill remaining threads off the hard way */ if (threads_created) { ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: Terminating %d threads that failed to exit.", my_pid, threads_created); } for (i = 0; i < threads_created; i++) { int *score_idx; TerminateThread(child_handles[i], 1); CloseHandle(child_handles[i]); /* Reset the scoreboard entry for the thread we just whacked */ score_idx = apr_hash_get(ht, &child_handles[i], sizeof(HANDLE)); if (score_idx) { ap_update_child_status_from_indexes(0, *score_idx, SERVER_DEAD, NULL); } } ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, "Child %lu: All worker threads have exited.", my_pid); CloseHandle(allowed_globals.jobsemaphore); apr_thread_mutex_destroy(allowed_globals.jobmutex); apr_thread_mutex_destroy(child_lock); if (use_acceptex) { apr_thread_mutex_destroy(qlock); CloseHandle(qwait_event); } apr_pool_destroy(pchild); CloseHandle(exit_event); }
static void *client_to_remote_server(void *arg) { struct client_to_rs_data *r = arg; char ip[sizeof("xxx:xxx:xxx:xxx")] = "0.0.0.0"; int rs_port = r->rs_port; int n = r->num; LOG1_THREAD("** Client for %s meant for getting readings from a remote server - Started! **\n", sensors_name[n]); const char *rs_ip_port_file = REMOTE_SERVER_IP_PORT_CONF_FILE; FILE *rs_ip_port_fp = fopen(rs_ip_port_file, "r"); if (rs_ip_port_fp) { LOG1_THREAD("Reading remote server ip and port from %s\n", rs_ip_port_file); bool fine = fscanf(rs_ip_port_fp, "%s", ip) == 1; if (!fine) { ERR1_THREAD("Something probably wrong with remote server ip or port - fscanf - %s\n", strerror(errno)); goto done; } fgetc(rs_ip_port_fp); // Skip space fclose(rs_ip_port_fp); rs_ip_port_fp = NULL; } else { ERR1_THREAD("Failed to read %s. fopen - %s\n", rs_ip_port_file, strerror(errno)); goto done; } struct sockaddr_in serv_addr = { 0, }; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(rs_port); LOG1_THREAD("Converting remote server ip . . .\n"); LOG1_THREAD("Remote server port: %d\n", rs_port); int af = AF_INET; int convert_ret = inet_pton(af, ip, &serv_addr.sin_addr); bool invalid_ip_str = convert_ret == 0; bool invalid_af_family = convert_ret == -1; if (invalid_ip_str) { ERR1_THREAD("Invalid ip str - %s\n", ip); goto done; } else if(invalid_af_family) { ERR1_THREAD("Invalid af family - %d\n", af); goto done; } LOG1_THREAD("Given remote server ip(%s) converted . . .\n", ip); strcpy(ip, LOCALHOST_IP); int emu_port = r->emu_port; free(r); r = NULL; struct sockaddr_in client_addr = { 0, }; client_addr.sin_family = AF_INET; client_addr.sin_port = htons(emu_port); LOG1_THREAD("Converting emu ip . . .\n"); LOG1_THREAD("Emu port: %d\n", emu_port); convert_ret = inet_pton(af, ip, &client_addr.sin_addr); invalid_ip_str = convert_ret == 0; invalid_af_family = convert_ret == -1; if (invalid_ip_str) { ERR1_THREAD("Invalid ip str - %s\n", ip); goto done; } else if(invalid_af_family) { ERR1_THREAD("Invalid af family - %d\n", af); goto done; } LOG1_THREAD("Given emulator ip(%s) converted . . .\n", ip); while (1) { if (client_to_rs_sockfd[n] != -1) { LOG1_THREAD("Closing client to remote server socket . . .\n"); close(client_to_rs_sockfd[n]); client_to_rs_sockfd[n] = -1; LOG1_THREAD("Closed!\n"); } LOG1_THREAD("Opening remote server socket . . .\n"); client_to_rs_sockfd[n] = socket(AF_INET, SOCK_STREAM, 0); if (client_to_rs_sockfd[n] == -1) { ERR1_THREAD("Socket - %s\n", strerror(errno)); goto done; } LOG1_THREAD("Remote server socket opened . . .\n"); LOG1_THREAD("Connecting . . .\n"); bool connected = connect(client_to_rs_sockfd[n], (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != -1; if (!connected) { ERR1_THREAD("Connect - %s\n", strerror(errno)); sleep(1); continue; } LOG1_THREAD("Connected . . .\n"); if (emu_sockfd[n] != -1) { LOG1_THREAD("Closing emu socket . . .\n"); close(emu_sockfd[n]); emu_sockfd[n] = -1; LOG1_THREAD("Closed!\n"); } LOG1_THREAD("Opening emu socket . . .\n"); emu_sockfd[n] = socket(AF_INET, SOCK_STREAM, 0); if (emu_sockfd[n] == -1) { ERR1_THREAD("socket - %s\n", strerror(errno)); goto done; } LOG1_THREAD("Emu socket opened!\n"); LOG1_THREAD("Connecting . . .\n"); connected = connect(emu_sockfd[n], (struct sockaddr *)&client_addr, sizeof(client_addr)) != -1; if (!connected) { ERR1_THREAD("connect - %s\n", strerror(errno)); goto done; } LOG1_THREAD("Connected!\n"); time_t seed = time(NULL); if (seed == -1) { ERR1_THREAD("time - Failed to generate a seed - %s\n", strerror(errno)); // Not a crtical error. So, we continue! } srand(seed); while (1) { size_t readings_size = n == EAccel ? ACCEL_READINGS_BUF_SIZE + 1 : n == EGyro ? GYRO_READINGS_BUF_SIZE + 1 : READINGS_BUF_SIZE + 1; char rs_readings[readings_size]; memset(rs_readings, 0, sizeof(rs_readings)); LOG1_THREAD("Receiving . . .\n"); ssize_t bytes_received = recvfrom(client_to_rs_sockfd[n], rs_readings, readings_size, MSG_WAITALL, NULL, 0); if (bytes_received == -1) { ERR1_THREAD("recvFrom - %s\n", strerror(errno)); break; } LOG1_THREAD("%zd bytes received!\n", bytes_received); LOG1_THREAD("Remote server readings: %s\n", rs_readings); LOG_READING; if (!bytes_received) { LOG1_THREAD("Seems like connection to remote server is lost. Will reconnect.\n"); break; } if (bytes_received != readings_size) { LOG1_THREAD("Partial data. Ignoring\n"); continue; } LOG1_THREAD("Sending to emulator via port redirection!\n"); ssize_t bytes_sent = sendto(emu_sockfd[n], rs_readings, readings_size, 0, NULL, 0); if (bytes_sent == -1) { ERR1_THREAD("sendto - %s\n", strerror(errno)); break; } else { LOG1_THREAD("%zd bytes wrote!\n", bytes_sent); } usleep(1000); } } done: if (client_to_rs_sockfd[n] != -1) { close(client_to_rs_sockfd[n]); client_to_rs_sockfd[n] = -1; } LOG1_THREAD("** Client for %s meant for getting readings from a remote server - Terminated! **\n", sensors_name[n]); cleanup_thread(n); return 0; }
static void *dummy_server(void *args) { struct dummy_server_data *d = args; int port = d->port; int n = d->num; LOG_DUMMY_S_THREAD("** Dummy server for %s on behalf of the emulator server - Started! **\n", sensors_name[n]); LOG_DUMMY_S_THREAD("** Port : %d\n", port); LOG_DUMMY_S_THREAD("** Server number : %d\n", n); free(d); d = NULL; struct sockaddr_in serv_addr = { 0 }; LOG_DUMMY_S_THREAD("Opening socket . . .\n"); dummy_server_listenfd[n] = socket(AF_INET, SOCK_STREAM, 0); if (dummy_server_listenfd[n] == -1) { ERR_DUMMY_S_THREAD("socket - Opening failed - %s\n", strerror(errno)); goto done; } LOG_DUMMY_S_THREAD("Opened!\n"); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); LOG_DUMMY_S_THREAD("Binding socket . . .\n"); bool bound = bind(dummy_server_listenfd[n], (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != -1; if (!bound && errno != EADDRINUSE) { // Due to port mapping with Qemu, this bind // may return EADDRINUSE. We just have to ignore it! ERR_DUMMY_S_THREAD("bind - Failed - %s %d\n", strerror(errno), errno); goto done; } LOG_DUMMY_S_THREAD("Bound!\n"); LOG_DUMMY_S_THREAD("Trying to listen . . .\n"); bool listening = listen(dummy_server_listenfd[n], 10) != -1; if (!listening) { ERR_DUMMY_S_THREAD("listen - Failed - %s\n", strerror(errno)); goto done; } LOG_DUMMY_S_THREAD("Listening!\n"); LOG_DUMMY_S_THREAD("Accepting connection . . .\n"); dummy_server_connfd[n] = accept(dummy_server_listenfd[n], (struct sockaddr*)NULL, NULL); if (dummy_server_connfd[n] == -1) { ERR_DUMMY_S_THREAD("accept - Failed - %s\n", strerror(errno)); goto done; } LOG_DUMMY_S_THREAD("Accepted!\n"); LOG_DUMMY_S_THREAD("Sleeping forever . . .\n"); sem_t dummy_sem = { { 0 } }; bool initzd = sem_init(&dummy_sem, 0, 0) != -1; if (!initzd) { ERR_DUMMY_S_THREAD("sem_init - Failed - %s\n", strerror(errno)); goto done; } bool waited = sem_wait(&dummy_sem) != -1; if (!waited) { LOG_DUMMY_S_THREAD("Couldn't sleep forever!\n"); LOG_DUMMY_S_THREAD("\n\n** CONTROL SHOULD NEVER REACH HERE!! **\n\n"); LOG_DUMMY_S_THREAD("\n\n** HELP ME!! I'M LOST!\n"); ERR_DUMMY_S_THREAD("sem_wait - Failed - %s\n", strerror(errno)); goto done; } done: cleanup_thread(n); LOG_DUMMY_S_THREAD("** Dummy server for %s on behalf of the emulator server - Terminated! **\n", sensors_name[n]); return NULL; }