@@ -39,6 +39,9 @@ struct scache_connection_node ctable[CONNECTION_HASH_ENTRIES] = { 0 };
3939int epfd;
4040volatile sig_atomic_t stop_soon = 0 ;
4141
42+ bool connection_stop_soon (){
43+ return stop_soon != 0 ;
44+ }
4245
4346struct connection_thread_arg
4447{
@@ -128,6 +131,8 @@ static int connection_non_blocking(int fd)
128131
129132void connection_close_listeners () {
130133 int fd;
134+
135+ WARN (" Closing %d listeners" , scache_listeners.listener_count );
131136
132137 for (uint32_t i = 0 ; i < scache_listeners.listener_count ; i++)
133138 {
@@ -242,23 +247,39 @@ int connection_open_listener(struct scache_bind ibind) {
242247 return -1 ;
243248}
244249
245- static scache_connection* connection_add (int fd) {
250+ static scache_connection* connection_add (int fd, listener_type client_type ) {
246251 scache_connection_node* node = &ctable[CONNECTION_HASH_KEY (fd)];
252+ scache_connection_node* newNode = NULL ;
253+
247254 if (node->connection .client_sock != -1 ) {
248255 while (node->next != NULL ) {
249256 assert (node->connection .client_sock != -1 );
250257 node = node->next ;
251258 }
252259
253- scache_connection_node* newNode = (scache_connection_node*)malloc (sizeof (scache_connection_node));
254- node-> next = newNode;
255- node = newNode ;
260+ newNode = (scache_connection_node*)malloc (sizeof (scache_connection_node));
261+ } else {
262+ newNode = node ;
256263 }
257264
258265 // Initialize connection
259- memset (node, 0 , sizeof (node)); /* .connection = {}, .next = NULL */
260- rbuf_init (&(node->connection .input ));
261- node->connection .client_sock = fd;
266+ memset (newNode, 0 , sizeof (*newNode)); /* .connection = {}, .next = NULL */
267+
268+ // safe to set first
269+ newNode->connection .ltype = client_type;
270+ if (client_type == cache_listener){
271+ newNode->connection .cache .target .key .fd = -1 ;
272+ }
273+ rbuf_init (&(newNode->connection .input ));
274+
275+ // do last as marks connection slot as used
276+ newNode->connection .client_sock = fd;
277+
278+ // this is a chained connection
279+ if (node != newNode){
280+ node->next = newNode;
281+ node = newNode;
282+ }
262283
263284 return &(node->connection );
264285}
@@ -383,6 +404,7 @@ static void* connection_handle_accept(void *arg)
383404 goto end;
384405 }
385406 } while (nfds == 0 && !stop_soon);
407+ assert (nfds >= 0 );
386408 int n = 0 ;
387409 int state = 1 ;
388410 while (n < nfds) {
@@ -394,67 +416,63 @@ static void* connection_handle_accept(void *arg)
394416 else if (events[n].events & EPOLLIN)
395417 {
396418 DEBUG (" [#] Accepting connection from fd %d of type %s\n " , fd, listener_type_string (our_type));
397- int client_sock;
398-
399- do
400- {
401- client_sock = accept (fd, NULL , NULL );
419+ int client_sock = accept (fd, NULL , NULL );
402420
403- if (client_sock < 0 ) {
404- if (errno == EAGAIN || errno == EWOULDBLOCK)
405- {
406- break ;
407- }
421+ if (client_sock < 0 ) {
422+ if (errno != EAGAIN && errno != EWOULDBLOCK)
423+ {
408424 WARN (" [#] accept() failed on fd %d of type %s. Error: %s" , fd, listener_type_string (our_type), strerror (errno));
409- break ;
410- }
411- else {
412- DEBUG (" [#] Accepted connection %d on fd %d of type %s\n " , client_sock, fd, listener_type_string (our_type));
413-
414- // Connection will be non-blocking
415- if (connection_non_blocking (client_sock) < 0 )
416- PFATAL (" Setting connection to non blocking failed on fd %d of type %s." , fd, listener_type_string (our_type));
417-
418- // Enable TCP CORK
419- setsockopt (client_sock, IPPROTO_TCP, TCP_CORK, &state, sizeof (state));
420-
421- connections_queued* q = (connections_queued*)malloc (sizeof (connections_queued));
422- if (q == NULL ){
423- close (client_sock);
424- WARN (" [#] failed to allocate memory for connection. Abandoning incoming connection." );
425- continue ;
426- }
427- q->client_sock = client_sock;
428- q->client_type = our_type;
429- q->next = NULL ;
430-
431- // Insert connection into queue
432- pthread_mutex_lock (&cq_lock);
433- if (cq_tail == NULL )
434- {
435- assert (cq_head == NULL );
436- cq_tail = q;
437- cq_head = q;
438- }
439- else
440- {
441- cq_tail->next = q;
442- cq_tail = q;
443- }
444- pthread_mutex_unlock (&cq_lock);
445-
446- // Write a signal
447- int res;
448- do {
449- res = write (eventfd, &u, sizeof (u));
450- if (res == -1 ){
451- PFATAL (" Unable to write to eventfd" );
452- }
453- assert (res == sizeof (u));
454- } while (!res);
455425 }
456426 n++;
457- } while (!stop_soon);
427+ continue ;
428+ }
429+ else {
430+ DEBUG (" [#] Accepted connection %d on fd %d of type %s\n " , client_sock, fd, listener_type_string (our_type));
431+
432+ // Connection will be non-blocking
433+ if (connection_non_blocking (client_sock) < 0 )
434+ PFATAL (" Setting connection to non blocking failed on fd %d of type %s." , fd, listener_type_string (our_type));
435+
436+ // Enable TCP CORK
437+ setsockopt (client_sock, IPPROTO_TCP, TCP_CORK, &state, sizeof (state));
438+
439+ connections_queued* q = (connections_queued*)malloc (sizeof (connections_queued));
440+ if (q == NULL ){
441+ close (client_sock);
442+ n++;
443+ WARN (" [#] failed to allocate memory for connection. Abandoning incoming connection." );
444+ continue ;
445+ }
446+ q->client_sock = client_sock;
447+ q->client_type = our_type;
448+ q->next = NULL ;
449+
450+ // Insert connection into queue
451+ pthread_mutex_lock (&cq_lock);
452+ if (cq_tail == NULL )
453+ {
454+ assert (cq_head == NULL );
455+ cq_tail = q;
456+ cq_head = q;
457+ }
458+ else
459+ {
460+ cq_tail->next = q;
461+ cq_tail = q;
462+ }
463+ pthread_mutex_unlock (&cq_lock);
464+
465+ // Write a signal
466+ int res;
467+ do {
468+ res = write (eventfd, &u, sizeof (u));
469+ if (res == -1 ){
470+ PFATAL (" Unable to write to eventfd" );
471+ }
472+ assert (res == sizeof (u));
473+ } while (!res);
474+ }
475+ n++;
458476 }
459477 }
460478 }
@@ -481,7 +499,7 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
481499 }
482500
483501 // Init Acceptor thread
484- connection_thread_arg* thread_arg = (connection_thread_arg*) malloc ( sizeof (connection_thread_arg) * 2 ) ;
502+ connection_thread_arg thread_arg[ 2 ] ;
485503 efd = eventfd (0 , 0 );
486504 thread_arg[0 ].type = cache_listener;
487505 thread_arg[1 ].type = mon_listener;
@@ -509,7 +527,6 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
509527 continue ;
510528 }
511529 PFATAL (" epoll_wait() failed" );
512- goto end;
513530 }
514531 } while (nfds == 0 && !stop_soon);
515532
@@ -521,7 +538,7 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
521538 {
522539 res = read (fd, &u, sizeof (u));
523540
524- while (true )
541+ while (!stop_soon )
525542 {
526543 // Dequeue
527544 pthread_mutex_lock (&cq_lock);
@@ -549,9 +566,8 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
549566
550567 // Handle connection
551568 DEBUG (" [#%d] A new %s socket was accepted %d\n " , fd, listener_type_string (client_type), client_sock);
552- scache_connection* connection = connection_add (client_sock);
569+ scache_connection* connection = connection_add (client_sock, client_type );
553570 assert (connection->client_sock == client_sock);
554- connection->ltype = client_type;
555571 connection_handler (connection);
556572
557573 // Add socket to epoll
@@ -628,12 +644,16 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
628644end:
629645 close (epfd);
630646
631- pthread_join (tid[0 ], NULL );
632- pthread_join (tid[1 ], NULL );
647+ errno = pthread_join (tid[0 ], NULL );
648+ if (errno != 0 ) {
649+ PFATAL (" failed to join cache thread" );
650+ }
651+ errno = pthread_join (tid[1 ], NULL );
652+ if (errno != 0 ) {
653+ PFATAL (" failed to join mon thread" );
654+ }
633655
634656 close (efd);
635-
636- free (thread_arg);
637657}
638658
639659/*
0 commit comments