Opened 13 years ago
Closed 7 years ago
#10552 closed defect (fixed)
TracMercurial hooks.py dies when using TortoiseHg
Reported by: | Owned by: | Christian Boos | |
---|---|---|---|
Priority: | normal | Milestone: | plugin - mercurial |
Component: | plugin/mercurial | Version: | |
Severity: | normal | Keywords: | TracMercurial, subprocess |
Cc: | franoleg@… | Branch: | |
Release Notes: |
Hooks pipe stdin. |
||
API Changes: | |||
Internal Changes: |
Description
In the hooks.py script it uses subprocess.Popen to call trac-admin. If you're running from the console it should be fine, but when you try to run from TortoiseHg on Windows you get a nice "helpful" message:
error: commit hook raised an exception: [Error 6] The handle is invalid
It took me a while but I finally tracked down the problem - apparently it's a more or less known issue with the subprocess module.
The fix is surprisingly simple - change this:
proc = subprocess.Popen(command, close_fds=close_fds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
to this:
proc = subprocess.Popen(command, close_fds=close_fds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
Apparently when there's no console on Windows (e.g. running Mercurial commits by way of TortoiseHg)
subprocess cannot inherit the standard handles when the process has no console, you have to create pipes for all 3 channels, and close those that are not needed. Python mailing list
Attachments (1)
Change History (9)
comment:1 by , 13 years ago
Milestone: | → plugin - mercurial |
---|
comment:2 by , 13 years ago
Use Popen.communicate, so it will not deadlock.
And use a file instead a PIPE if you expect too much output, because a PIPE is not buffered.
comment:3 by , 13 years ago
Cc: | added |
---|
comment:4 by , 12 years ago
I have a hgweb repo with hooks:
commit = python:tracext.hg.hooks.add_changesets changegroup = python:tracext.hg.hooks.add_changesets
When hosted with Apache mod_wsgi, the hooks script will alternative between success and failure, e.g. push n = success, push n+1 = failure, push n+2 = success, etc.
This problem is fixed after applying the solution suggested here.
comment:6 by , 12 years ago
Can't you simply do:
ui.write(stdout)
instead of iterating over all characters and writing them one by one?
comment:7 by , 12 years ago
Yup, didn't notice that. In this case, I guess we can just do:
ui.write(proc.communicate()[0])
comment:8 by , 7 years ago
Release Notes: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | new → closed |
Pushed patch with changes from comment:6 in [60/mercurial-plugin].
It's probably not quite as simple as that. Creating a pipe for
stdout
andstderr
, but not reading it, risks blocking the subprocess if it outputs too much data.What we should probably do is define two separate pipes for
stdout
andstderr
, read them while the subprocess is running, and pass the data toui.write()
andui.write_err()
, respectively. That way, TortoiseHg would even get a chance to relay any issues to the user.