fix(process): reap entire process group on cmd.Cancel - #39143
Conversation
|
Please trim down on comments. |
…arent Assisted-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Royce Remer <royceremer@gmail.com>
1dd219d to
bc21fdd
Compare
|
What do you think about this bc21fdd ? |
…escalate SIGINT -> SIGKILL Assisted-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Royce Remer <royceremer@gmail.com>
|
@wxiaoguang while a much bigger refactor, your change will be safer because mine relied on callers to use I've added a few test cases to prove this, and my proposed fix is just to introduce a default 10s (configurable) wait on Cancel() before escalating to SIGKILL: 9e336b1 |
I intentionally didn't do that because it will just cause pid data-race problems. You can ask AI about the PID-race details. So I strongly prefer to revert 9e336b1 (Actually, I mean, it needs to be reverted) And, I don't see why the SIGTERM would be ignored in real world for our cases. If it would happen, I already prepared |
Assisted-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Royce Remer <royceremer@gmail.com>
Good point, although technically SIGINT suffers from this as well.
Maybe not 'ignored' in real-world scenarios, but certainly blocked longer than what we might be willing to wait. How long is too-long is really only known by the caller, but I could see scenarios where that external renderer or ssh call sites hang on some connection. Is 5 minutes too-long? Is 30 seconds? It looks like |
I don't see it would really affect real world use cases. And there is no easy solution for the PID reuse data-race. I believe we can take the graceful kill (SIGTERM) as default behavior, if anything wrong, just switch to SIGKILL. |
No, it's not right. "there is no easy solution for the PID reuse data-race." |
I think the real-world use-case is pretty theoretical, for sure, but this would reduce the window of pid reuse from however long since the process was started, to probably nanoseconds. |
Let's just try to use SIGTERM as the default signal in production to see whether there would be real problems. If yes, just switch to SIGKILL. |
* origin/main: (30 commits) docs: Update CHANGELOG for release 1.27.3 (go-gitea#39170) [skip ci] Updated translations via Crowdin [skip ci] Updated translations via Crowdin fix(process): reap entire process group on cmd.Cancel (go-gitea#39143) feat(web): Add org removal functionality to admin user details page (go-gitea#38013) fix(actions): run every due schedule exactly once per occurrence (go-gitea#39078) refactor: pagination/pager (go-gitea#39162) [skip ci] Updated translations via Crowdin enhance(actions): make workflow dispatch choice dropdown support search (go-gitea#39154) fix(web): populate the reason for "cannot commit to branch" in web editor commit form (go-gitea#39155) refactor(automerge): fix error handling, populate recent automerge tasks on restart (go-gitea#39001) chore(frontend): avoid loading CSS twice in vite dev mode (go-gitea#39160) fix(packages): preserve SemVer prerelease identifiers in Swift Registry (go-gitea#39156) [skip ci] Updated translations via Crowdin ci(snap): pack snaps without an LXD container (go-gitea#39152) chore: apply golangci "forbidigo" to all packages (go-gitea#39151) refactor: drop two unmaintained dependencies, rename the byte size helpers (go-gitea#39083) fix(actions): keep step-level continue-on-error expressions unevaluated (go-gitea#39141) [skip ci] Updated translations via Crowdin feat: add deploy tokens (go-gitea#37306) ... # Conflicts: # modelmigration/migrations.go # modelmigration/v28/v352.go # routers/private/hook_pre_receive.go # templates/repo/release/new.tmpl
I ran into an issue where many client disconnects during clone operations were leaving expensive
git pack-objects --revs --thin --stdout --delta-base-offsetprocesses in gitea. These processes would still run to completion, but the underlying http request which initiated them had long since been cancelled.The bug is subtle, but the
cmd.Cancelcall would target the original PID, while git commands regularly fork several child processes which are not cancelled. Because their parent was cancelled, they'd get reparented to either the gitea process or pid 1 depending on the kernel.This change uses the negative process group to cancel the entire process group together instead of just the parent.