A websocket implementation for zig
0

Configure Feed

Select the types of activity you want to include in your feed.

Use mutex to protect handleconn of doublefree

This can happen if the client is disconneted just before the server is shutdown.

https://github.com/karlseguin/websocket.zig/issues/80

Karl Seguin (Sep 14, 2025, 10:55 AM +0800) 4deaaef2 f7e2c02b

+15 -6
+15 -6
src/server/server.zig
··· 775 775 } 776 776 777 777 fn cleanupConn(self: *Self, hc: *HandlerConn(H)) void { 778 - if (hc.reader) |*reader| { 779 - if (self.small_buffer_pool) |*sbp| { 780 - sbp.release(reader.static); 781 - } else { 782 - self.allocator.free(reader.static); 778 + { 779 + hc.cleanup.lock(); 780 + defer hc.cleanup.unlock(); 781 + if (hc.reader) |*reader| { 782 + if (self.small_buffer_pool) |*sbp| { 783 + sbp.release(reader.static); 784 + } else { 785 + self.allocator.free(reader.static); 786 + } 787 + hc.reader = null; 783 788 } 784 789 } 785 790 self.conn_manager.cleanup(hc); ··· 792 797 793 798 // called for each hc when shutting down 794 799 fn shutdownCleanup(self: *Self, hc: *HandlerConn(H)) void { 800 + hc.cleanup.lock(); 801 + defer hc.cleanup.unlock(); 795 802 if (hc.reader) |*reader| { 796 803 if (self.small_buffer_pool == null) { 797 804 self.allocator.free(reader.static); 798 805 } 806 + hc.reader = null; 799 807 } 800 808 } 801 809 }; ··· 1086 1094 reader: ?Reader, 1087 1095 socket: posix.socket_t, // denormalization from conn.stream.handle 1088 1096 handshake: ?*Handshake.State, 1097 + cleanup: Thread.Mutex = .{}, 1089 1098 compression: ?Compression = null, 1090 1099 next: ?*HandlerConn(H) = null, 1091 1100 prev: ?*HandlerConn(H) = null, ··· 1272 1281 // This is sloppy and leaves things in an unrecoverable state. To keep 1273 1282 // things clean, we should call self.cleanup(hc) on each entry in the list 1274 1283 // but that does a bunch of things we don't need if we know that we're 1275 - // shutting down - like returning data to the pools, nd popping items 1284 + // shutting down - like returning data to the pools, and popping items 1276 1285 // out of the list. 1277 1286 fn shutdownList(head: ?*HandlerConn(H), worker: anytype) void { 1278 1287 var next_node = head;