Skip to content

Native shop-admin signup SIGBUS in toUser → dtRequiredToIso (downstream of @perryts/mysql MyDateTime.toDate corruption) #859

Description

@proggeramlug

Symptom

Native-compiled skelpo-shop-admin (./build/server) at perry 0.5.914 crashes with SIGBUS / exit 138 during POST /v1/auth/signup. The first INSERT INTO users commits (visible in MySQL), then the process dies — curl gets Empty reply from server and the connection drops. tsx server/main.ts against the same source + same DB returns the correct JSON / HTTP 201.

This is the v0.5.914 surfacing of what at v0.5.912 was a silent body-0/HTTP 200 — same site, harder failure now that the Invalid-Date sentinel is in.

Pinned crash site (checkpoint-instrumented trace)

Instrumented server/persistence/users.ts::createUser/getUserById/toUser:

U1 INSERT                      ← createUser INSERT runs
U2 done, pre getUserById       ← INSERT resolved, row visible
G1 pre queryOne                ← getUserById entered
G2 queryOne obj                ← SELECT returned the row
T0 enter   (toUser entered)
T1 id=019e2fac-...             ← bufToId(r.id) works
T2 emailVerified=null          ← dtToIso(null) works
T3 totp=null                    ← dtToIso(null) works
                                ← SIGBUS. No T4.

Next statement is dtRequiredToIso(r.createdAt), which calls r.createdAt.toDate().getTime() on the MyDateTime object the @perryts/mysql driver decoded. That .toDate() call is where the process dies.

Root cause

The proximate trigger is #788 — closure-captured numeric params read as 0 inside object-literal : Date method (filed separately). MyDateTime.toDate() is exactly that shape, so for every decoded DATETIME the captured y/mo/d/... read as 0 inside the method and new Date(Date.UTC(0, ...)) produces a year-0 Date (-62155492224598 ms). When that value flows into dtRequiredToIso → d.toISOString() and the resulting string into perry's JSON / fastify reply path, something in the formatting / serialization chain assumes a finite, plausible timestamp and segfaults.

In a standalone repro of just the MyDateTime.toDate().toISOString() shape (no Fastify, no mysql connection — see #788) the same code returns a garbage 0000-05-15T17:29:36.598Z string without crashing. The shop-admin path additionally goes through fastify's JSON reply, the post-#748 wait_for_promise condvar path, and likely the @perryts/mysql worker-thread → main-thread Date hand-off. One of those layers can't survive a year-0 / Invalid Date and faults.

Repro

Local: clean checkout of skelpo-shop-admin, cargo build --release of perry at HEAD (e18cdb07 / v0.5.914), then:

mysql -uroot -e "DROP DATABASE IF EXISTS shopadmin; CREATE DATABASE shopadmin"
KEK_BASE64=... JWT_SIGNING_KEY_PEM=... DB_DSN='mysql://root:@127.0.0.1:3306/shopadmin' \
  BIND_ADDR='127.0.0.1:18080' ./build/server &
curl -X POST http://127.0.0.1:18080/v1/auth/signup \
     -H 'content-type: application/json' \
     -d '{"email":"x@y.com","password":"correct-horse-battery-staple","accountName":"X"}'
# → curl: (52) Empty reply from server; server process exits 138.

tsx server/main.ts against the same DB+env returns the correct {accessToken, refreshToken, expiresAt, user, account} payload with HTTP 201 and all five tables populated.

Tracking history

This is the same end-user failure that drove #665 and #748:

Suggested fix scope

  1. Fix AsyncLocalStorage: real async-context tracking across await / microtasks / timers #788 (the captures) — that should be enough for the user's signup to work end-to-end. The corrupt-Date path stops producing year-0 values and toISOString returns the real timestamp.
  2. Independently, find the downstream layer that segfaults on a year-0/Invalid Date and harden it — same value at the same call site shouldn't take down the process. (My standalone repro of the same shape returns a garbage string without crashing, so the segfault is specific to one of: fastify reply path, @perryts/mysql worker→main thread Date crossing, or wait_for_promise resuming with a Date argument it doesn't expect.)

Perry version at repro: 0.5.914.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions