multithreading - Make new connections when blocked in a select() call -
i have 2 threads:
thread a: it's select() loop. perform socket handling reading operations, such accepting new connections, receiving data.
while (1) { fd_zero(&fdreadset); numactivesockets = 0; (std::unordered_map<socket, tcpsocket*>::iterator = m_sock_table.begin(); != m_sock_table.end(); it++) { numactivesockets++; fd_set(it->first, &fdreadset); } int ret; bool haslisten = false; if (( ret = select(numactivesockets, &fdreadset, null, null, null)) == socket_error) { printf("select failed, error code = %d\n", wsagetlasterror()); return -1; } (std::unordered_map<socket, tcpsocket*>::iterator = m_sock_table.begin(); != m_sock_table.end(); it++) { if (fd_isset(it->first, &fdreadset)) { if (it->first == tcpsocket::m_listen_sock) { if (!haslisten) { sockaddr_in sock_addr; int socklength = sizeof(sock_addr); socket sock = accept(it->first, (sockaddr *) &sock_addr, &socklength); tcpsocket * socket = new tcpsocket(); socket->m_sock = sock; m_sock_table[sock] = socket; = m_sock_table.begin(); haslisten = true; } } else { char * buffer = it->second->getwritebuffer(); int numread = recv(it->first, buffer, socket_buffer_size, 0); if (numread == socket_error) { int err = wsagetlasterror(); if (err == wsaeconnreset) { printf("connection [%i]: reset received. closing socket\n", it->first); closesocket(it->first); = socketvector.erase(it->first); // iterator invalidated after erase } else { printf("recv failed. error code = %d\n", err); return -1; } } else if (numread == 0)//connection close { printf("connection [%i]: graceful exit. closing socket\n", it->first); closesocket(it->first); = socketvector.erase(it->first); // iterator invalidated after erase } else { /* process received data */ } } } } }
thread b: allow application perform connect() establish new connections. if connect() successful, add returned socket m_sock_table.
i have socket table called m_sock_table holds sockets. use m_sock_table initialize fdreadset used in select().
-----------problem-----------------
if thread blocked select(), , @ same time thread b establish new connection through connect(), application wouldn't able receive data new connection, because fdreadset has not been updated withed new connected socket.
what way solve problem? or design wrong start?
you use signal doesn't other interrupting system call:
#include <signal.h> void do_nothing() { } struct sigaction sa; sa.sa_handler = do_nothing; sigemptyset(sa.sa_mask); #ifdef sa_interrupt sa.sa_flags = sa_interrupt; #else sa.sa_flags = 0; #endif sigaction(sigusr1, &sa, 0);
then, in thread b, after starting new connection, send signal, after making sure thread handle it:
/* need done once, needed in every thread other */ sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, sigusr1) pthread_sigmask(sig_block, &sigs, 0); /* each time create new connection */ kill(getpid, sigusr1);
with above, select return eintr error -- check , loop (adding new connection set).
Comments
Post a Comment