Skip to content

Conversation

@leosvelperez
Copy link
Member

@leosvelperez leosvelperez commented Nov 14, 2025

Current Behavior

When a continuous task depends on another continuous task and the dependent task exits with an error, the parent task continues running indefinitely. The task execution never terminates, leaving processes running in the background.

For example, if task a (continuous) depends on task b (continuous), and task b exits with error code 1, task a will continue running even though its dependency failed.

Expected Behavior

When a continuous task exits (with any exit code), the failure should be propagated to dependent tasks:

  1. The failed continuous task should be marked as failed
  2. Dependent continuous tasks should be marked as skipped
  3. All affected continuous tasks should be killed
  4. Task execution should terminate with an error

Changes Made

1. Restore Error Handling in Continuous Task Exit Handlers

  • Re-added the cleaningUp flag that was removed in a previous TUI-related commit
  • Modified onExit handlers for both regular and shared continuous tasks to:
    • Check if the task exited during normal cleanup vs. unexpectedly
    • Call complete() with 'failure' status for unexpected exits
    • Log error messages for debugging

2. Fix cleanUpUnneededContinuousTasks() Logic

The previous implementation always added initializingTaskIds to the needed set, even when those tasks were already completed. This prevented dependency tasks from being killed when the top-level task exited.

Fixed by:

  • Only adding tasks from initializingTaskIds if they are still incomplete
  • Keeping dependencies of incomplete tasks alive
  • This ensures continuous tasks are killed when no longer needed, whether a dependency fails or a top-level task exits

3. Prevent Status Overwrites

Added a check in onExit handlers to only set status to Stopped if the task hasn't already been completed. This prevents the async onExit callback from overwriting the correct status (like 'skipped' or 'failure') with 'Stopped'.

4. Fix Signal Handling in PseudoTtyProcess.kill()

The Rust pseudo-terminal defaults to SIGINT when no signal is provided, which does not reliably terminate child processes in PTY sessions.

Fixed by:

  • Defaulting to SIGTERM in the JavaScript wrapper (rather than changing the Rust default)
  • The JS wrapper is the API boundary that should match Node.js semantics, where childProcess.kill(undefined) defaults to SIGTERM
  • The Rust default of SIGINT is appropriate for interactive use (Ctrl-C), while programmatic cleanup needs SIGTERM
  • This ensures child processes are properly killed when runningTask.kill() is called

File: packages/nx/src/tasks-runner/pseudo-terminal.ts

Technical Details

The fix leverages the existing task failure propagation mechanism in complete() instead of using process.exit(1), which:

  • Allows proper cleanup through normal execution flow
  • Respects the --bail flag configuration
  • Works correctly with both TUI and non-TUI modes
  • Maintains consistency with how other task failures are handled

@leosvelperez leosvelperez self-assigned this Nov 14, 2025
@leosvelperez leosvelperez requested a review from a team as a code owner November 14, 2025 16:17
@vercel
Copy link

vercel bot commented Nov 14, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nx-dev Ready Ready Preview Nov 17, 2025 4:59pm

@netlify
Copy link

netlify bot commented Nov 14, 2025

Deploy Preview for nx-docs ready!

Name Link
🔨 Latest commit 812906d
🔍 Latest deploy log https://app.netlify.com/projects/nx-docs/deploys/691b52b873fb940007d818a9
😎 Deploy Preview https://deploy-preview-33492--nx-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@nx-cloud
Copy link
Contributor

nx-cloud bot commented Nov 14, 2025

View your CI Pipeline Execution ↗ for commit 812906d

Command Status Duration Result
nx affected --targets=lint,test,test-kt,build,e... ✅ Succeeded 29m 22s View ↗
nx run-many -t check-imports check-lock-files c... ✅ Succeeded 2m 37s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 11s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 2s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2025-11-17 17:27:51 UTC


// we're not cleaning up, so this is an unexpected exit, fail the task
if (!this.cleaningUp) {
console.error(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not going to show up in the task output.. can you fix this in a followup PR please?

@FrozenPandaz FrozenPandaz merged commit 7e00ec4 into master Nov 25, 2025
21 checks passed
@FrozenPandaz FrozenPandaz deleted the nxc-3370 branch November 25, 2025 14:49
FrozenPandaz pushed a commit that referenced this pull request Nov 25, 2025
)

## Current Behavior

When a continuous task depends on another continuous task and the
dependent task exits with an error, the parent task continues running
indefinitely. The task execution never terminates, leaving processes
running in the background.

For example, if task `a` (continuous) depends on task `b` (continuous),
and task `b` exits with error code 1, task `a` will continue running
even though its dependency failed.

## Expected Behavior

When a continuous task exits (with any exit code), the failure should be
propagated to dependent tasks:

1. The failed continuous task should be marked as failed
2. Dependent continuous tasks should be marked as skipped
3. All affected continuous tasks should be killed
4. Task execution should terminate with an error

---

## Changes Made

### 1. Restore Error Handling in Continuous Task Exit Handlers

- Re-added the `cleaningUp` flag that was removed in a previous
TUI-related commit
- Modified `onExit` handlers for both regular and shared continuous
tasks to:
  - Check if the task exited during normal cleanup vs. unexpectedly
  - Call `complete()` with 'failure' status for unexpected exits
  - Log error messages for debugging

### 2. Fix `cleanUpUnneededContinuousTasks()` Logic

The previous implementation always added `initializingTaskIds` to the
needed set, even when those tasks were already completed. This prevented
dependency tasks from being killed when the top-level task exited.

Fixed by:

- Only adding tasks from `initializingTaskIds` if they are still
incomplete
- Keeping dependencies of incomplete tasks alive
- This ensures continuous tasks are killed when no longer needed,
whether a dependency fails or a top-level task exits

### 3. Prevent Status Overwrites

Added a check in `onExit` handlers to only set status to `Stopped` if
the task hasn't already been completed. This prevents the async `onExit`
callback from overwriting the correct status (like 'skipped' or
'failure') with 'Stopped'.

### 4. Fix Signal Handling in `PseudoTtyProcess.kill()`

The Rust pseudo-terminal defaults to SIGINT when no signal is provided,
which does not reliably terminate child processes in PTY sessions.

Fixed by:

- Defaulting to SIGTERM in the JavaScript wrapper (rather than changing
the Rust default)
- The JS wrapper is the API boundary that should match Node.js
semantics, where `childProcess.kill(undefined)` defaults to SIGTERM
- The Rust default of SIGINT is appropriate for interactive use
(Ctrl-C), while programmatic cleanup needs SIGTERM
- This ensures child processes are properly killed when
`runningTask.kill()` is called

**File:** `packages/nx/src/tasks-runner/pseudo-terminal.ts`

## Technical Details

The fix leverages the existing task failure propagation mechanism in
`complete()` instead of using `process.exit(1)`, which:

- Allows proper cleanup through normal execution flow
- Respects the `--bail` flag configuration
- Works correctly with both TUI and non-TUI modes
- Maintains consistency with how other task failures are handled
@github-actions
Copy link
Contributor

github-actions bot commented Dec 1, 2025

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 1, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants