@@ -192,6 +192,15 @@ export fn run_xev_poll_read(fd: c_int, g: GPtr) void {
192192 const slot = & fd_slots [idx ];
193193 if (! slot .active ) return ;
194194
195+ slot .read_g = g ;
196+ if (slot .read_armed and slot .read_completion .state () == .active ) return ;
197+
198+ slot .read_completion = .{};
199+ slot .read_ctx = .{
200+ .slot = slot ,
201+ .generation = slot .generation ,
202+ };
203+ slot .read_armed = true ;
195204 if (builtin .os .tag == .windows ) {
196205 slot .read_completion = .{
197206 .op = .{
@@ -200,13 +209,13 @@ export fn run_xev_poll_read(fd: c_int, g: GPtr) void {
200209 .buffer = .{ .slice = &.{} },
201210 },
202211 },
203- .userdata = slot ,
212+ .userdata = & slot . read_ctx ,
204213 .callback = readPollCallback ,
205214 };
206215 loop .add (& slot .read_completion );
207216 } else {
208217 const file = File .initFd (handle );
209- file .poll (& loop , & slot .read_completion , .read , FdSlot , slot , & pollCallback );
218+ file .poll (& loop , & slot .read_completion , .read , CompletionContext , & slot . read_ctx , & pollCallback );
210219 }
211220}
212221
@@ -251,7 +260,10 @@ fn readPollCallback(
251260 _ : * Completion ,
252261 result : xev.Result ,
253262) CallbackAction {
254- const s : * FdSlot = @ptrCast (@alignCast (userdata orelse return .disarm ));
263+ const ctx : * CompletionContext = @ptrCast (@alignCast (userdata orelse return .disarm ));
264+ const s = ctx .slot orelse return .disarm ;
265+ if (! s .active or ctx .generation != s .generation ) return .disarm ;
266+
255267 if (ready_callback ) | cb | {
256268 const idx = (@intFromPtr (s ) - @intFromPtr (& fd_slots [0 ])) / @sizeOf (FdSlot );
257269 const fd : c_int = @intCast (idx );
0 commit comments