@@ -69,6 +69,7 @@ struct connections_queued
6969static volatile connections_queued* cq_head = NULL ;
7070static volatile connections_queued* cq_tail = NULL ;
7171static pthread_mutex_t cq_lock;
72+ static bool cq_lock_initialized = false ;
7273
7374/* Methods */
7475static bool connection_event_update (scache_connection* conn, uint32_t events) {
@@ -104,6 +105,10 @@ void connection_setup(struct scache_binds cache_binds, struct scache_binds monit
104105 if (scache_listeners.listeners == NULL ){
105106 FATAL (" Unable to allocate memory for listeners" );
106107 }
108+ memset (scache_listeners.listeners , 0 , sizeof (struct listener_entry ) * scache_listeners.listener_count );
109+ for (uint32_t j = 0 ; j < scache_listeners.listener_count ; j++) {
110+ scache_listeners.listeners [j].fd = -1 ;
111+ }
107112
108113 // Caching
109114 for (i = 0 ; i < cache_binds.num ; i++)
@@ -156,12 +161,15 @@ void connection_close_listeners() {
156161 for (uint32_t i = 0 ; i < scache_listeners.listener_count ; i++)
157162 {
158163 fd = scache_listeners.listeners [i].fd ;
159- scache_listeners.listeners [i].fd = -1 ;
160- close (fd);
164+ scache_listeners.listeners [i].fd = -1 ;
165+ if (fd >= 0 ) {
166+ close (fd);
167+ }
161168 }
162169
163170 free (scache_listeners.listeners );
164171 scache_listeners.listeners = NULL ;
172+ scache_listeners.listener_count = 0 ;
165173}
166174
167175static int connection_open_bind (struct scache_bind ibind, int listenfd)
@@ -494,6 +502,7 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
494502 {
495503 PFATAL (" mutex init failed" );
496504 }
505+ cq_lock_initialized = true ;
497506
498507 // Prepare a non blocking eventfd for thread communication
499508 efd = eventfd (0 , EFD_NONBLOCK);
@@ -739,9 +748,13 @@ void connection_cleanup() {
739748 connection_close_listeners ();
740749 }
741750
742- // free active connections
743- for (auto it = connections.begin (); it != connections.end (); ++it) {
744- connection_cleanup_http (*it);
751+ // Free active connections while erasing set nodes as we go so the set
752+ // itself releases all allocator-owned memory during shutdown.
753+ while (!connections.empty ()) {
754+ auto it = connections.begin ();
755+ scache_connection* connection = *it;
756+ connections.erase (it);
757+ connection_cleanup_http (connection);
745758 }
746759
747760 // free queued connections
@@ -750,4 +763,91 @@ void connection_cleanup() {
750763 cq_head = cq_head->next ;
751764 free (temp);
752765 }
753- }
766+ cq_tail = NULL ;
767+ if (cq_lock_initialized) {
768+ pthread_mutex_destroy (&cq_lock);
769+ cq_lock_initialized = false ;
770+ }
771+ }
772+
773+ void connection_release_inherited_fds_after_fork () {
774+ if (scache_listeners.listeners != NULL ) {
775+ for (uint32_t i = 0 ; i < scache_listeners.listener_count ; i++) {
776+ int fd = scache_listeners.listeners [i].fd ;
777+ scache_listeners.listeners [i].fd = -1 ;
778+ if (fd >= 0 ) {
779+ close (fd);
780+ }
781+ }
782+ }
783+
784+ for (auto connection : connections) {
785+ if (connection->client_sock >= 0 ) {
786+ close (connection->client_sock );
787+ connection->client_sock = -1 ;
788+ }
789+ }
790+
791+ for (connections_queued* queued = (connections_queued*)cq_head; queued != NULL ; queued = queued->next ) {
792+ if (queued->client_sock >= 0 ) {
793+ close (queued->client_sock );
794+ queued->client_sock = -1 ;
795+ }
796+ }
797+
798+ if (epfd > 0 ) {
799+ close (epfd);
800+ epfd = -1 ;
801+ }
802+ }
803+
804+ void connection_cleanup_after_fork () {
805+ DEBUG (" Performing post-fork cleanup\n " );
806+
807+ connections_queued* temp;
808+ if (scache_listeners.listeners != NULL ) {
809+ for (uint32_t i = 0 ; i < scache_listeners.listener_count ; i++) {
810+ int fd = scache_listeners.listeners [i].fd ;
811+ scache_listeners.listeners [i].fd = -1 ;
812+ if (fd >= 0 ) {
813+ close (fd);
814+ }
815+ }
816+ free (scache_listeners.listeners );
817+ scache_listeners.listeners = NULL ;
818+ scache_listeners.listener_count = 0 ;
819+ }
820+
821+ while (!connections.empty ()) {
822+ auto it = connections.begin ();
823+ scache_connection* connection = *it;
824+ connections.erase (it);
825+
826+ http_cleanup (connection);
827+ if (connection->client_sock >= 0 ) {
828+ close (connection->client_sock );
829+ connection->client_sock = -1 ;
830+ }
831+ free (connection);
832+ }
833+
834+ while (cq_head != NULL ) {
835+ temp = (connections_queued*)cq_head;
836+ cq_head = cq_head->next ;
837+ if (temp->client_sock >= 0 ) {
838+ close (temp->client_sock );
839+ }
840+ free (temp);
841+ }
842+ cq_tail = NULL ;
843+
844+ if (epfd > 0 ) {
845+ close (epfd);
846+ epfd = -1 ;
847+ }
848+
849+ if (cq_lock_initialized) {
850+ pthread_mutex_destroy (&cq_lock);
851+ cq_lock_initialized = false ;
852+ }
853+ }
0 commit comments