Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | not available | ||||
Proposed branch: | lp:~songofacandy/bzr/fix-524560 | ||||
Merge into: | lp:bzr/2.0 | ||||
Diff against target: |
117 lines (+52/-7) 3 files modified
bzrlib/atomicfile.py (+1/-1) bzrlib/osutils.py (+47/-2) bzrlib/transport/local.py (+4/-4) |
||||
To merge this branch: | bzr merge lp:~songofacandy/bzr/fix-524560 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Vincent Ladeuil | Approve | ||
Martin Packman (community) | Approve | ||
Andrew Bennetts | Approve | ||
Review via email: mp+19737@code.launchpad.net |
Commit message
Description of the change
methane (songofacandy) wrote : | # |
I've found open with mode="wbN" is enough.
mode 'N' means NOINHERIT on win32 and ignored on Linux.
Should I remove osutils.open and add 'N' flag directly?
John A Meinel (jameinel) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
INADA Naoki wrote:
> I've found open with mode="wbN" is enough.
> mode 'N' means NOINHERIT on win32 and ignored on Linux.
>
> Should I remove osutils.open and add 'N' flag directly?
If that works, I would recommend it. But we need to make sure that it
doesn't cause problems with Python 2.4.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAku
ZogAn1zgWNTubK4
=UidF
-----END PGP SIGNATURE-----
methane (songofacandy) wrote : | # |
> INADA Naoki wrote:
> > I've found open with mode="wbN" is enough.
> > mode 'N' means NOINHERIT on win32 and ignored on Linux.
> >
> > Should I remove osutils.open and add 'N' flag directly?
>
> If that works, I would recommend it. But we need to make sure that it
> doesn't cause problems with Python 2.4.
>
> John
> =:->
I confirmed that glibc doesn't use 'N' for mode so it just ignore the 'N'.
But I don't know about other libc. (on Solaris, FreeBSD, MacOS, etc...)
So I think using 'N' only on win32 is safe.
Python 2.4 uses msvcrt71 (VC++2003?) and msdn doesn't document 'N' mode
and O_NOINHERIT. But os module in Python 2.4 have O_NOINHERIT so fcntl.h in
VC++2003 should have O_NOINHERIT.
I don't know the file is inherited to child process or not.
But I installed Python 2.4 and ``open('foo', 'wbN').
Martin Packman (gz) wrote : | # |
Some general comments:
* Adding O_NOINHERIT to the default flags bzr uses seems sensible.
* Don't like the style of having shadows in osutils that are almost-
> Python 2.4 uses msvcrt71 (VC++2003?) and msdn doesn't document 'N' mode
> and O_NOINHERIT. But os module in Python 2.4 have O_NOINHERIT so fcntl.h in
> VC++2003 should have O_NOINHERIT.
> I don't know the file is inherited to child process or not.
> But I installed Python 2.4 and ``open('foo', 'wbN').
MSDN is correct, it does *not* work on Pythons compiled with VS < 2005. The open succeeds but the flag is ignored. I threw together some quick tests that show this, and don't think this change should go in untested or this lightly documented.
methane (songofacandy) wrote : | # |
> * Don't like the style of having shadows in osutils that are almost-but-not-
> quite builtins or standard library functions.
So, which name is suitable?
* open_noinherit()
* open_noshare()
* or other name...
> > Python 2.4 uses msvcrt71 (VC++2003?) and msdn doesn't document 'N' mode
> > and O_NOINHERIT. But os module in Python 2.4 have O_NOINHERIT so fcntl.h in
> > VC++2003 should have O_NOINHERIT.
> > I don't know the file is inherited to child process or not.
> > But I installed Python 2.4 and ``open('foo', 'wbN').
> works.
>
> MSDN is correct, it does *not* work on Pythons compiled with VS < 2005. The
> open succeeds but the flag is ignored. I threw together some quick tests that
> show this, and don't think this change should go in untested or this lightly
> documented.
Should we support this case on Python 2.4 on Windows?
If should, using os.fdopen(
http://
Martin Pool (mbp) wrote : | # |
On 23 February 2010 12:54, INADA Naoki <email address hidden> wrote:
>> * Don't like the style of having shadows in osutils that are almost-but-not-
>> quite builtins or standard library functions.
>
> So, which name is suitable?
>
> * open_noinherit()
> * open_noshare()
> * or other name...
open_file.
I agree with gzlist that using exactly the same name is likely to
cause confusion, but the fact that you want noinherit seems more like
an option than an entirely different function. Or would it be
feasible to just pass the right option to plain open()?
--
Martin <http://
Martin Packman (gz) wrote : | # |
> > * Don't like the style of having shadows in osutils that are almost-but-not-
> > quite builtins or standard library functions.
Just realised there's a clash with another current merge proposal here:
<https:/
Which I guess proves my point.
> So, which name is suitable?
>
> * open_noinherit()
> * open_noshare()
> * or other name...
I like the first one best there, but pine for a better way...
> Should we support this case on Python 2.4 on Windows?
> If should, using os.fdopen(
> http://
Python 2.5 is also pre-VS2005. Using O_NOINHERIT does work on everything, though if it's the best option I don't know.
Martin Packman (gz) wrote : | # |
> I like the first one best there, but pine for a better way...
Nope, can't find one. Only vile hacks and Vista-or-later functionality.
Personally, I wouldn't object to putting 'N' in the open flags of any long-lived file bazaar uses, and documenting that people should expect things to break with Python < 2.6 if they don't use paramiko. About the only person that'll harm will be me, and I've not run into this bug yet.
methane (songofacandy) wrote : | # |
> On 23 February 2010 12:54, INADA Naoki <email address hidden> wrote:
> >> * Don't like the style of having shadows in osutils that are almost-but-
> not-
> >> quite builtins or standard library functions.
> >
> > So, which name is suitable?
> >
> > * open_noinherit()
> > * open_noshare()
> > * or other name...
>
> open_file.
>
> I agree with gzlist that using exactly the same name is likely to
> cause confusion, but the fact that you want noinherit seems more like
> an option than an entirely different function. Or would it be
> feasible to just pass the right option to plain open()?
>
OK, I agree open_file is good.
I've changed the name.
methane (songofacandy) wrote : | # |
> > > * Don't like the style of having shadows in osutils that are almost-but-
> not-
> > > quite builtins or standard library functions.
>
> Just realised there's a clash with another current merge proposal here:
> <https:/
> ownership/
Thanks for point it.
open_file() should fixes this and it.
> > Should we support this case on Python 2.4 on Windows?
> > If should, using os.fdopen(
> > http://
>
> Python 2.5 is also pre-VS2005. Using O_NOINHERIT does work on everything,
> though if it's the best option I don't know.
OK. I should use O_NOINHERIT flag instead of 'N' mode.
I've fixed it now.
Martin Packman (gz) wrote : | # |
Okay, I think some version of this should go in.
I've got a competing branch that does the minimal 'N' flag adding here:
<https:/
But I was under the impression that the all-in-one installer used the latest Python. As it's still on 2.5 my branch wouldn't actually fix the edge case in the bug for most people.
Vincent Ladeuil (vila) wrote : | # |
@Martin [gz], damn, our messages crossed on the wire, I had already sent the pqm submission long before I saw your message...
Can you do a merge proposal explaining your branch intent or
is it now irrelevant (you said "some version of should go in"
and Naoki's version hs landed in 2.0 now) ?
Martin Packman (gz) wrote : | # |
What you've landed is fine Vincent, Naoki's more complicated version is needed for the older Python versions.
I don't see it on bzr.dev yet though, it needs upmerging still?
Vincent Ladeuil (vila) wrote : | # |
yes, I'll will do that (merging 2.0 in 2.1 and 2.1 into bzr.dev) asap.
Vincent Ladeuil (vila) wrote : | # |
Done.
Preview Diff
1 | === modified file 'bzrlib/atomicfile.py' |
2 | --- bzrlib/atomicfile.py 2009-03-23 14:59:43 +0000 |
3 | +++ bzrlib/atomicfile.py 2010-02-23 08:13:17 +0000 |
4 | @@ -60,7 +60,7 @@ |
5 | |
6 | self.realfilename = filename |
7 | |
8 | - flags = os.O_EXCL | os.O_CREAT | os.O_WRONLY |
9 | + flags = os.O_EXCL | os.O_CREAT | os.O_WRONLY | osutils.O_NOINHERIT |
10 | if mode == 'wb': |
11 | flags |= osutils.O_BINARY |
12 | elif mode != 'wt': |
13 | |
14 | === modified file 'bzrlib/osutils.py' |
15 | --- bzrlib/osutils.py 2009-10-08 03:55:30 +0000 |
16 | +++ bzrlib/osutils.py 2010-02-23 08:13:17 +0000 |
17 | @@ -74,8 +74,11 @@ |
18 | # be opened in binary mode, rather than text mode. |
19 | # On other platforms, O_BINARY doesn't exist, because |
20 | # they always open in binary mode, so it is okay to |
21 | -# OR with 0 on those platforms |
22 | +# OR with 0 on those platforms. |
23 | +# O_NOINHERIT and O_TEXT exists only on win32 too. |
24 | O_BINARY = getattr(os, 'O_BINARY', 0) |
25 | +O_TEXT = getattr(os, 'O_TEXT', 0) |
26 | +O_NOINHERIT = getattr(os, 'O_NOINHERIT', 0) |
27 | |
28 | |
29 | def get_unicode_argv(): |
30 | @@ -639,7 +642,7 @@ |
31 | def sha_file_by_name(fname): |
32 | """Calculate the SHA1 of a file by reading the full text""" |
33 | s = sha() |
34 | - f = os.open(fname, os.O_RDONLY | O_BINARY) |
35 | + f = os.open(fname, os.O_RDONLY | O_BINARY | O_NOINHERIT) |
36 | try: |
37 | while True: |
38 | b = os.read(f, 1<<16) |
39 | @@ -1907,3 +1910,45 @@ |
40 | if use_cache: |
41 | _cached_concurrency = concurrency |
42 | return concurrency |
43 | + |
44 | +if sys.platform == 'win32': |
45 | + def open_file(filename, mode='r', bufsize=-1): |
46 | + """This function works like builtin ``open``. But use O_NOINHERIT |
47 | + flag so file handle is not inherited to child process. |
48 | + So deleting or renaming closed file that opened with this function |
49 | + is not blocked by child process. |
50 | + """ |
51 | + writing = 'w' in mode |
52 | + appending = 'a' in mode |
53 | + updating = '+' in mode |
54 | + binary = 'b' in mode |
55 | + |
56 | + flags = O_NOINHERIT |
57 | + # see http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.71%29.aspx |
58 | + # for flags for each modes. |
59 | + if binary: |
60 | + flags |= O_BINARY |
61 | + else: |
62 | + flags |= O_TEXT |
63 | + |
64 | + if writing: |
65 | + if updating: |
66 | + flags |= os.O_RDWR |
67 | + else: |
68 | + flags |= os.O_WRONLY |
69 | + flags |= os.O_CREAT | os.O_TRUNC |
70 | + elif appending: |
71 | + if updating: |
72 | + flags |= os.O_RDWR |
73 | + else: |
74 | + flags |= os.O_WRONLY |
75 | + flags |= os.O_CREAT | os.O_APPEND |
76 | + else: #reading |
77 | + if updating: |
78 | + flags |= os.O_RDWR |
79 | + else: |
80 | + flags |= os.O_RDONLY |
81 | + |
82 | + return os.fdopen(os.open(filename, flags), mode, bufsize) |
83 | +else: |
84 | + open_file = open |
85 | |
86 | === modified file 'bzrlib/transport/local.py' |
87 | --- bzrlib/transport/local.py 2009-06-23 01:59:20 +0000 |
88 | +++ bzrlib/transport/local.py 2010-02-23 08:13:17 +0000 |
89 | @@ -42,8 +42,8 @@ |
90 | from bzrlib.transport import Transport, Server |
91 | |
92 | |
93 | -_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY |
94 | -_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY |
95 | +_append_flags = os.O_CREAT | os.O_APPEND | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT |
96 | +_put_non_atomic_flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | osutils.O_BINARY | osutils.O_NOINHERIT |
97 | |
98 | |
99 | class LocalTransport(Transport): |
100 | @@ -160,7 +160,7 @@ |
101 | transport._file_streams[canonical_url].flush() |
102 | try: |
103 | path = self._abspath(relpath) |
104 | - return open(path, 'rb') |
105 | + return osutils.open_file(path, 'rb') |
106 | except (IOError, OSError),e: |
107 | if e.errno == errno.EISDIR: |
108 | return LateReadError(relpath) |
109 | @@ -329,7 +329,7 @@ |
110 | # initialise the file |
111 | self.put_bytes_non_atomic(relpath, "", mode=mode) |
112 | abspath = self._abspath(relpath) |
113 | - handle = open(abspath, 'wb') |
114 | + handle = osutils.open_file(abspath, 'wb') |
115 | if mode is not None: |
116 | self._check_mode_and_size(abspath, handle.fileno(), mode) |
117 | transport._file_streams[self.abspath(relpath)] = handle |
It would be nice to have a test for this, but I'm not sure what that would look like.
This looks like a good candidate for the 2.0 branch, so thanks for preparing it against that.