@barnum/barnum 0.0.0-main-5cffb40b → 0.0.0-main-8245e869

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/run.js +31 -0
  2. package/package.json +1 -1
  3. package/src/run.ts +31 -0
package/dist/run.js CHANGED
@@ -145,6 +145,11 @@ function spawnBarnumJson(configJson, logLevel) {
145
145
  cliArgs.push("--log-level", logLevel);
146
146
  }
147
147
  return new Promise((resolve, reject) => {
148
+ // NOT detached: barnum makes ITSELF a process-group leader (setpgid(0,0) in
149
+ // barnum_cli) and installs its own SIGINT/SIGTERM handler that killpg()s the
150
+ // group — barnum plus the `tsx worker.ts` children it spawns. Spawning
151
+ // detached here would call setpgid in the child too and collide with that
152
+ // (EPERM), so we leave grouping to barnum.
148
153
  const child = nodeSpawn(binaryResolution.path, cliArgs, {
149
154
  stdio: ["inherit", "pipe", "pipe"],
150
155
  });
@@ -157,7 +162,33 @@ function spawnBarnumJson(configJson, logLevel) {
157
162
  stderrChunks.push(chunk);
158
163
  process.stderr.write(chunk);
159
164
  });
165
+ // Forward a parent termination signal to barnum, then remove our handlers
166
+ // and re-raise on ourselves so the parent exits with the conventional
167
+ // signal status. An interactive Ctrl+C already reaches barnum via the
168
+ // terminal's foreground group, but a programmatic kill of the parent (e.g.
169
+ // a supervisor, or `/loop`) does NOT — without this forward, barnum (and
170
+ // its workers, possibly mid-`git` holding an index.lock) would orphan.
171
+ // barnum's own signal handler then killpg()s its worker group.
172
+ const forwardAndExit = (signal) => {
173
+ if (child.pid !== undefined) {
174
+ try {
175
+ process.kill(child.pid, signal);
176
+ }
177
+ catch {
178
+ // Already exited, or we lost the race — nothing to do.
179
+ }
180
+ }
181
+ process.off("SIGINT", onSigint);
182
+ process.off("SIGTERM", onSigterm);
183
+ process.kill(process.pid, signal);
184
+ };
185
+ const onSigint = () => forwardAndExit("SIGINT");
186
+ const onSigterm = () => forwardAndExit("SIGTERM");
187
+ process.on("SIGINT", onSigint);
188
+ process.on("SIGTERM", onSigterm);
160
189
  const cleanup = () => {
190
+ process.off("SIGINT", onSigint);
191
+ process.off("SIGTERM", onSigterm);
161
192
  try {
162
193
  unlinkSync(configFilePath);
163
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barnum/barnum",
3
- "version": "0.0.0-main-5cffb40b",
3
+ "version": "0.0.0-main-8245e869",
4
4
  "description": "Barnum: composable workflow pipelines",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/run.ts CHANGED
@@ -191,6 +191,11 @@ function spawnBarnumJson<TOut>(
191
191
  }
192
192
 
193
193
  return new Promise<TOut>((resolve, reject) => {
194
+ // NOT detached: barnum makes ITSELF a process-group leader (setpgid(0,0) in
195
+ // barnum_cli) and installs its own SIGINT/SIGTERM handler that killpg()s the
196
+ // group — barnum plus the `tsx worker.ts` children it spawns. Spawning
197
+ // detached here would call setpgid in the child too and collide with that
198
+ // (EPERM), so we leave grouping to barnum.
194
199
  const child = nodeSpawn(binaryResolution.path, cliArgs, {
195
200
  stdio: ["inherit", "pipe", "pipe"],
196
201
  });
@@ -207,7 +212,33 @@ function spawnBarnumJson<TOut>(
207
212
  process.stderr.write(chunk);
208
213
  });
209
214
 
215
+ // Forward a parent termination signal to barnum, then remove our handlers
216
+ // and re-raise on ourselves so the parent exits with the conventional
217
+ // signal status. An interactive Ctrl+C already reaches barnum via the
218
+ // terminal's foreground group, but a programmatic kill of the parent (e.g.
219
+ // a supervisor, or `/loop`) does NOT — without this forward, barnum (and
220
+ // its workers, possibly mid-`git` holding an index.lock) would orphan.
221
+ // barnum's own signal handler then killpg()s its worker group.
222
+ const forwardAndExit = (signal: NodeJS.Signals) => {
223
+ if (child.pid !== undefined) {
224
+ try {
225
+ process.kill(child.pid, signal);
226
+ } catch {
227
+ // Already exited, or we lost the race — nothing to do.
228
+ }
229
+ }
230
+ process.off("SIGINT", onSigint);
231
+ process.off("SIGTERM", onSigterm);
232
+ process.kill(process.pid, signal);
233
+ };
234
+ const onSigint = () => forwardAndExit("SIGINT");
235
+ const onSigterm = () => forwardAndExit("SIGTERM");
236
+ process.on("SIGINT", onSigint);
237
+ process.on("SIGTERM", onSigterm);
238
+
210
239
  const cleanup = () => {
240
+ process.off("SIGINT", onSigint);
241
+ process.off("SIGTERM", onSigterm);
211
242
  try {
212
243
  unlinkSync(configFilePath);
213
244
  } catch {