Commit 8933203
game_eval: bound eval with a deadline and always free the temp node (#488)
* game_eval: bound eval with a deadline and always free the temp node
Evaluated GDScript that awaits something which never completes (a signal
that never fires, a timer on a paused tree) hung _handle_eval's
`await temp_node.execute()` with no escape hatch: the reply and
queue_free() below were never reached, leaking the eval Node and pinning
the request until the dispatcher's 15s deferred budget / the server's 15s
command timeout fired it back as an opaque INTERNAL_ERROR.
Telemetry shows this is ~19-20% of all game_eval calls, steady across
2.5.6-2.5.9 and all three platforms (500+ installs), with failed-call
durations clustered at the 10-15s timeout thresholds vs ~40ms for
successes.
Drive execute() as a fire-and-forget coroutine recording into a holder,
poll process_frame until done or an 8s deadline (comfortably under the
15s ceiling, with round-trip margin), and on timeout detach + free the
node and reply with an actionable mcp:eval_error instead of letting the
request ride to INTERNAL_ERROR. Does not cover CPU-bound loops with no
await (they block the main thread, including this poll).
Refs #487
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* game_eval: document timeout ordering + extract eval reply helpers
Follow-up cleanups from a code review of the deadline guard, all
behavior-preserving:
- Document the load-bearing cross-file timeout ordering (game 8s <
editor 10s < dispatcher 15s). Only the game-side EVAL_TIMEOUT_SEC
guard emits the actionable "Eval exceeded 8s" message; the editor's
fallback timer emits a generic one. The relationship lives in three
separate files with nothing enforcing it, so a tweak to any one
could silently swap the actionable diagnostic for the generic
timeout. Note added at both EVAL_TIMEOUT_SEC and request_game_eval.
- Note the accepted residual leak in _drive_eval: an await that never
fires leaves the coroutine suspended and its (detached) node unfreed
for the game-process lifetime. GDScript can't cancel a suspended
coroutine; still strictly better than the pre-#487 in-tree leak.
- Extract _reply_eval_error / _reply_eval_response to match the file's
existing _reply_error / _reply_game_command_error convention,
replacing four inline EngineDebugger.send_message call sites.
Verified in a live editor (4.6.3): normal eval, sub-deadline await,
and the 8s timeout path all return correctly through the new helpers;
no node leak; headless --import is parse-clean.
Refs #487
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent 4b3f76d commit 8933203
2 files changed
Lines changed: 103 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
331 | 331 | | |
332 | 332 | | |
333 | 333 | | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
334 | 341 | | |
335 | 342 | | |
336 | 343 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
519 | 519 | | |
520 | 520 | | |
521 | 521 | | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
522 | 548 | | |
523 | 549 | | |
524 | 550 | | |
525 | 551 | | |
526 | 552 | | |
527 | | - | |
| 553 | + | |
528 | 554 | | |
529 | 555 | | |
530 | 556 | | |
| |||
543 | 569 | | |
544 | 570 | | |
545 | 571 | | |
546 | | - | |
547 | | - | |
| 572 | + | |
| 573 | + | |
548 | 574 | | |
549 | 575 | | |
550 | 576 | | |
551 | 577 | | |
552 | 578 | | |
553 | 579 | | |
554 | 580 | | |
555 | | - | |
556 | | - | |
557 | | - | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
558 | 616 | | |
559 | 617 | | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
560 | 649 | | |
561 | | - | |
| 650 | + | |
562 | 651 | | |
563 | 652 | | |
564 | 653 | | |
| |||
0 commit comments