Skip to content

socket.write() through a Map-stored object property is dropped (no sendto) from a timer callback on Linux #5540

Description

@proggeramlug

Summary

On a Perry-native Linux x86_64 binary, socket.write(buf) is silently dropped (no sendto syscall, bytes never hit the wire) when the socket is reached through a property of a Map-stored object and the write happens from a timer (setInterval) callback. The identical write through a top-level const socket from the same timer context works.

This is distinct from #5021 (write-from-'data'-handler, now fixed). It blocks @perryts/mysql again: its 0.1.7 fix correctly detects Perry (process.versions.perry) and defers writes to a setInterval flush pump, but the pump writes via CONN_STATES.get(id).sock.write(bytes) — exactly the dropped pattern — so password auth still times out (Got timeout reading communication packets).

Minimal repro

Dropped — 0 sendto:

import * as net from 'net';
interface St { sock: ReturnType<typeof net.createConnection>; }
const M = new Map<number, St>(); const id = 1;
M.set(id, { sock: net.createConnection(3306, '127.0.0.1') });   // any peer that speaks first
let done = false;
function flush(i: number): void { const st = M.get(i); if (st === undefined) return; st.sock.write(Buffer.alloc(105, 0x41)); }
M.get(id)!.sock.on('data', () => {
  if (done) return; done = true;
  const iv = setInterval(() => { flush(id); clearInterval(iv); }, 0);
  setTimeout(() => process.exit(0), 2000);
});

perry compile repro.ts -o r && strace -f -e trace=sendto ./rno sendto(…, 105).

Works — sendto fires: the same write but on a top-level const socket directly inside the setInterval (no Map/object-property indirection):

const iv = setInterval(() => { s.write(Buffer.alloc(105, 0x41)); clearInterval(iv); }, 0);   // s = module const

Observed in the real driver (@perryts/mysql 0.1.7)

Instrumented trace of a password connect:

recv len=94            # greeting
scheduleFlush q=1
PUMP fired             # setInterval pump runs
FLUSH id=1
flush-write len=105    # st.sock.write(bytes) is called ...
<no sendto>            # ... but nothing reaches the wire
failStartup connection timeout after 10000ms

Environment

perry 0.5.1182 (runtime reports process.versions.perry = 0.4.71), Ubuntu 26.04 x86_64, MySQL 8.4. Empty-password connections work (zero-length auth response ⇒ the failing write path isn't exercised); Node works. Companion: PerryTS/mysql#2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions