Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

TypeScript: single-instance lock for the listening socket

オープン
#46 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
38/100
issue の種類
機能追加
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
c, docker, node.js, typescript

調査の方向性

Read the existing Go and Rust lock implementations, then inspect the TypeScript listener and ts/Dockerfile. Run the skipped openListener concurrent test in ts/src/listen.test.ts and review spec/listener.qnt plus the TypeScript exception in spec/listener-design.md. Done means the locked configuration and TypeScript lock tests pass, concurrency leaves exactly one server, and reproducibility remains bit-for-bit.

索引モデルが issue の本文から書いたものです。

説明

Type: Enhancement

Is your feature request related to a problem?

#45 adds a single-instance lock to Go and Rust: flock(LOCK_EX|LOCK_NB) on <listen-socket>.lock, held for as long as the process runs. Node has no flock. On Node 22, fs.flock is undefined, there is no fcntl locking, and O_EXLOCK doesn't exist on Linux. So TypeScript relies only on the "in use" check (it connect(2)s to the existing socket before deleting it). That leaves a race between checking and deleting:

  1. A connects: refused, so the socket is stale.
  2. B connects: refused, so the socket is stale.
  3. A deletes the socket and binds. A is now live.
  4. B deletes A's live socket and binds. A keeps running, but nothing can reach it.

This only happens when two TypeScript instances start within a few milliseconds of each other on the same path. A second instance that starts after the first is listening is still refused. The race is recorded formally as raceWithoutLockTest in spec/listener.qnt, using the listener_unlocked module. It is a documented exception to the equal-peers rule; see spec/listener-design.md, section "TypeScript exception".

Describe the solution

A small in-repo N-API addon, about 30 lines of C, exposing flock(fd, LOCK_EX|LOCK_NB), with no npm dependency. TypeScript then uses the same lock as Go and Rust: the same file path, mode, O_NOFOLLOW and error messages.

This needs a change to ts/Dockerfile, which currently runs npm ci --ignore-scripts on stagex/pallet-nodejs. Either allow install scripts for that one package, or build the addon in an explicit step on stagex/pallet-nodejs or a StageX C-toolchain stage. make verify-reproducible-ts must stay bit-for-bit reproducible.

Done when:

  • the listener_locked Quint configuration covers TypeScript as well;
  • the skipped test openListener concurrent in ts/src/listen.test.ts is un-skipped and passes (8 instances started together, repeated 50 times, and exactly one ends up serving);
  • TypeScript passes the same lock unit tests as Go and Rust (symlink refused, unreadable lock file, released on SIGKILL).

Describe alternatives

  • An fs-ext-style npm addon: rejected. It's an external dependency built by install scripts.
  • Calling flock(1) from a shell: rejected. util-linux isn't in the runtime image.
  • An abstract-namespace lock socket: rejected. It's Linux-only and scoped to a network namespace, so two containers sharing a socket volume wouldn't see each other's lock.
  • A lock-free link(2)/rename(2) replace-and-check-inode protocol: rejected. It can still orphan a socket when three instances start together, and a live socket briefly disappears while it's being put back.

Which implementation(s) would this affect?

  • Go
  • Rust
  • TypeScript
  • Quint specification
  • All

Additional context

Follow-up to #45.

主要言語
Rust
スター
2
フォーク
0
平均マージ
14時間 26分
マージ済み PR(30日)
27

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

ChainSafe/docker-socket-policy のほかの issue

ChainSafe/docker-socket-policy の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。