static void _ensure_pool_return_gracefully_handles_address_already_returned( void ) { void * item; pool_t pool; pool_init( &pool, 4, 1, allocator_default( ) ); item = pool_take( &pool ); pool_return( &pool, item ); pool_return( &pool, item ); pool_cleanup( &pool ); }
static void _ensure_pool_return_gracefully_handles_address_not_in_pool( void ) { unsigned item_not_in_pool; pool_t pool; pool_init( &pool, 4, 1, allocator_default( ) ); pool_return( &pool, &item_not_in_pool ); TEST_REQUIRE( pool_take( &pool ) != &item_not_in_pool ); TEST_REQUIRE( pool_take( &pool ) == 0 ); pool_cleanup( &pool ); }
static void _ensure_pool_take_reuses_returned_elements( void ) { void * item; pool_t pool; pool_init( &pool, 4, 1, allocator_default( ) ); item = pool_take( &pool ); pool_return( &pool, item ); TEST_REQUIRE( pool_take( &pool ) == item ); pool_cleanup( &pool ); }
void thread_func_wrapper(void *pArg) { THREAD_FUNC_WRAPPER_ARG_T wrap; char tmp[128]; int rc = 0; memcpy(&wrap, pArg, sizeof(THREAD_FUNC_WRAPPER_ARG_T)); ((THREAD_FUNC_WRAPPER_ARG_T *)pArg)->flags = 0; logutil_tid_add(pthread_self(), wrap.tid_tag); //pthread_cond_broadcast(((THREAD_FUNC_WRAPPER_ARG_T *) pArg)->pcond); //fprintf(stderr, "%u THREAD_FUNC pConn:0x%x inuse:%d\n", pthread_self(), wrap.pConn, wrap.pConn->pool.inuse); // // Handle any SSL handshaking on the connection thread, to avoid blocking the accept loop // if((wrap.pConn->sd.netsocket.flags & NETIO_FLAG_SSL_TLS)) { if((rc = netio_acceptssl(&wrap.pConn->sd.netsocket)) < 0) { LOG(X_ERROR("Closing non-SSL connection on port %d from %s:%d"), htons(INET_PORT(wrap.pConn->pListenCfg->sa)), FORMAT_NETADDR(wrap.pConn->sd.sa, tmp, sizeof(tmp)), htons(INET_PORT(wrap.pConn->sd.sa))); } } if(rc == 0) { // // Call the wrapper's thread procedure // wrap.thread_func(wrap.pConn); } //fprintf(stderr, "%d THREAD_FUNC DONE pConn:0x%x inuse:%d\n", pthread_self(), wrap.pConn, wrap.pConn->pool.inuse); netio_closesocket(&wrap.pConn->sd.netsocket); pool_return(wrap.pConnPool, &wrap.pConn->pool); logutil_tid_remove(pthread_self()); //fprintf(stderr, "%u THREAD_FUNC DONE pConn:0x%x inuse:%d\n", pthread_self(), wrap.pConn, wrap.pConn->pool.inuse); }
int srvlisten_loop(SRV_LISTENER_CFG_T *pListenCfg, void *thread_func) { int salen; THREAD_FUNC_WRAPPER_ARG_T wrapArg; CLIENT_CONN_T *pConn; SOCKET_DESCR_T sdclient; int rc = -1; const char *s; //pthread_cond_t cond; pthread_mutex_t mtx; TIME_VAL tv0, tv1; char tmp[128]; #if defined(__APPLE__) int sockopt = 0; #endif // __APPLE__ if(!pListenCfg || !pListenCfg->pnetsockSrv || !pListenCfg->pConnPool || !thread_func || pListenCfg->pConnPool->numElements <= 0) { return -1; } //memset(&saSrv, 0, sizeof(saSrv)); memset(&sdclient.netsocket, 0, sizeof(sdclient.netsocket)); //salen = sizeof(saSrv); //if(getsockname(pListenCfg->pnetsockSrv->sock, (struct sockaddr *) &saSrv, (socklen_t *) &salen) != 0) { // LOG(X_ERROR("getsockopt failed on server socket")); //} pthread_mutex_init(&mtx, NULL); //pthread_cond_init(&cond, NULL); while(!g_proc_exit) { salen = sizeof(sdclient.sa); if((NETIOSOCK_FD(sdclient.netsocket) = accept(PNETIOSOCK_FD(pListenCfg->pnetsockSrv), (struct sockaddr *) &sdclient.sa, (socklen_t *) &salen)) == INVALID_SOCKET) { if(!g_proc_exit) { LOG(X_ERROR("%saccept failed on %s:%d"), ((pListenCfg->pnetsockSrv->flags & NETIO_FLAG_SSL_TLS) ? "SSL " : ""), //inet_ntoa(saSrv.sin_addr), ntohs(saSrv.sin_port)); FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa))); } break; } if(g_proc_exit) { break; } sdclient.netsocket.flags = pListenCfg->pnetsockSrv->flags; // // Find an available client thread to process the client request // if((pConn = (CLIENT_CONN_T *) pool_get(pListenCfg->pConnPool)) == NULL) { LOG(X_WARNING("No available connection for %s:%d (max:%d) on port %d"), FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), ntohs(INET_PORT(sdclient.sa)), pListenCfg->pConnPool->numElements, ntohs(INET_PORT(pListenCfg->sa))); netio_closesocket(&sdclient.netsocket); continue; } #if defined(__APPLE__) sockopt = 1; if(setsockopt(NETIOSOCK_FD(sdclient.netsocket), SOL_SOCKET, SO_NOSIGPIPE, (char*) &sockopt, sizeof(sockopt)) != 0) { LOG(X_ERROR("Failed to set SO_NOSIGPIPE")); } #endif // __APPLE__ //pConn->psrvsaListen = &saSrv; //memcpy(&pConn->srvsaListen, &saSrv, sizeof(pConn->srvsaListen)); LOG(X_DEBUG("Accepted connection on port %d from %s:%d"), htons(INET_PORT(pListenCfg->sa)), FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), htons(INET_PORT(sdclient.sa))); pthread_attr_init(&pConn->attr); pthread_attr_setdetachstate(&pConn->attr, PTHREAD_CREATE_DETACHED); memset(&pConn->sd.netsocket, 0, sizeof(pConn->sd.netsocket)); NETIO_SET(pConn->sd.netsocket, sdclient.netsocket); memcpy(&pConn->sd.sa, &sdclient.sa, INET_SIZE(sdclient)); pConn->pListenCfg = pListenCfg; NETIOSOCK_FD(sdclient.netsocket) = INVALID_SOCKET; wrapArg.thread_func = thread_func; wrapArg.pConnPool = pListenCfg->pConnPool; wrapArg.pConn = pConn; wrapArg.flags = 1; wrapArg.tid_tag[0] = '\0'; if((s = logutil_tid_lookup(pthread_self(), 0)) && s[0] != '\0') { snprintf(wrapArg.tid_tag, sizeof(wrapArg.tid_tag), "%s-%u", s, pConn->pool.id); } //wrapArg.pcond = &cond; //fprintf(stderr, "%d CALLING wrap: 0x%x pConn:0x%x\n", pthread_self(), &wrapArg, wrapArg.pConn); if((rc = pthread_create(&pConn->ptd, &pConn->attr, (void *) thread_func_wrapper, (void *) &wrapArg)) != 0) { LOG(X_ERROR("Unable to create connection handler thread on port %d from %s:%d (%d %s)"), htons(INET_PORT(pListenCfg->sa)), FORMAT_NETADDR(sdclient.sa, tmp, sizeof(tmp)), htons(INET_PORT(sdclient.sa)), rc, strerror(rc)); netio_closesocket(&pConn->sd.netsocket); pool_return(pListenCfg->pConnPool, &pConn->pool); wrapArg.flags = 0; //pthread_cond_broadcast(&cond); break; } pthread_attr_destroy(&pConn->attr); // // be careful not to reuse the same wrapArg instance // since the stack variable arguments could get // overwritten by the next loop iteration, before the thread proc is // invoked // //fprintf(stderr, "wait start\n"); tv0 = timer_GetTime(); //if(wrapArg.flags == 1) { // // It seems that calling pthread_cond_wait here to check if the thread creation is // complete is not completely reliable and portable, so we do the lame way // of sleeping and polling. // //pthread_cond_wait(&cond, &mtx); while(wrapArg.flags == 1) { usleep(100); if(((tv1 = timer_GetTime()) - tv0) / TIME_VAL_MS > 1000) { LOG(X_WARNING("Abandoning wait for connection thread start on port %d from %s:%d"), htons(INET_PORT(pListenCfg->sa)), FORMAT_NETADDR(pListenCfg->sa, tmp, sizeof(tmp)), ntohs(INET_PORT(pListenCfg->sa))); break; } } //fprintf(stderr, "THREAD STARTED AFTER %lld ns\n", (timer_GetTime() - tv0)); //} //fprintf(stderr, "wait done\n"); //while(wrapArg.flag == 1) { // usleep(10000); //} } //pthread_cond_destroy(&cond); pthread_mutex_destroy(&mtx); return rc; }