This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2012年08月21日 02:26 by trent, last changed 2022年04月11日 14:57 by admin.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| test_readlink.sh | trent, 2012年08月24日 01:12 | |||
| Messages (15) | |||
|---|---|---|---|
| msg168731 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月21日 02:26 | |
FreeBSD slaves are running into this: ====================================================================== ERROR: test_copy2_symlinks (test.test_shutil.TestShutil) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/test/test_shutil.py", line 490, in test_copy2_symlinks shutil.copy2(src_link, dst, follow_symlinks=False) File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/shutil.py", line 237, in copy2 copyfile(src, dst, follow_symlinks=follow_symlinks) File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/shutil.py", line 107, in copyfile os.symlink(os.readlink(src), dst) TypeError: embedded NUL character ====================================================================== ERROR: test_copy_symlinks (test.test_shutil.TestShutil) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/test/test_shutil.py", line 463, in test_copy_symlinks shutil.copy(src_link, dst, follow_symlinks=False) File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/shutil.py", line 221, in copy copyfile(src, dst, follow_symlinks=follow_symlinks) File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/shutil.py", line 107, in copyfile os.symlink(os.readlink(src), dst) TypeError: embedded NUL character ====================================================================== FAIL: test_copytree_symlinks (test.test_shutil.TestShutil) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildslave/cpython/3.x.snakebite-freebsd91-amd64/build/Lib/test/test_shutil.py", line 606, in test_copytree_symlinks os.path.join(src_dir, 'file.txt')) AssertionError: '/tmp/tmpqlihz5/src/file.' != '/tmp/tmpqlihz5/src/file.txt' - /tmp/tmpqlihz5/src/file. + /tmp/tmpqlihz5/src/file.txt ? +++ Haven't had time to debug it any further yet. Have no clue what's going on either just from a cursory look at the error messages. Not sure if it's ZFS related like the other FreeBSD issues. |
|||
| msg168749 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月21日 07:28 | |
Looks like os.readlink() is busted:
> /home/trent/src/cpython/Lib/shutil.py(107)copyfile()
-> os.symlink(os.readlink(src), dst)
(Pdb) s
TypeError: embedded NUL character
> /home/trent/src/cpython/Lib/shutil.py(107)copyfile()
-> os.symlink(os.readlink(src), dst)
(Pdb) os.readlink(src)
'/tmp/tmpr3obfj/foo\x00\x00\x00\x00\x00\x00'
(Pdb) p src
'/tmp/tmpr3obfj/baz'
(Pdb) l
102 # XXX What about other special files? (sockets, devices...)
103 if stat.S_ISFIFO(st.st_mode):
104 raise SpecialFileError("`%s` is a named pipe" % fn)
105
106 if not follow_symlinks and os.path.islink(src):
107 -> os.symlink(os.readlink(src), dst)
108 else:
109 with open(src, 'rb') as fsrc:
110 with open(dst, 'wb') as fdst:
111 copyfileobj(fsrc, fdst)
112 return dst
> /home/trent/src/cpython/Lib/shutil.py(107)copyfile()
-> os.symlink(os.readlink(src), dst)
(Pdb) s
TypeError: embedded NUL character
> /home/trent/src/cpython/Lib/shutil.py(107)copyfile()
-> os.symlink(os.readlink(src), dst)
(Pdb) os.readlink(src)
'/tmp/tmpr3obfj/foo\x00\x00\x00\x00\x00\x00'
(Pdb) p src
'/tmp/tmpr3obfj/baz'
(Pdb) l
102 # XXX What about other special files? (sockets, devices...)
103 if stat.S_ISFIFO(st.st_mode):
104 raise SpecialFileError("`%s` is a named pipe" % fn)
105
106 if not follow_symlinks and os.path.islink(src):
107 -> os.symlink(os.readlink(src), dst)
108 else:
109 with open(src, 'rb') as fsrc:
110 with open(dst, 'wb') as fdst:
111 copyfileobj(fsrc, fdst)
112 return dst
i.e.:
(Pdb) os.readlink(src)
'/tmp/tmpr3obfj/foo\x00\x00\x00\x00\x00\x00'
Started another session with gdb, set a breakpoint at posix_readlink:
Breakpoint 1, posix_readlink (self=0x800909858, args=0x805ec2840, kwargs=0x0)
at ./Modules/posixmodule.c:7007
7007 int dir_fd = DEFAULT_DIR_FD;
(gdb) l
7002
7003 static PyObject *
7004 posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
7005 {
7006 path_t path;
7007 int dir_fd = DEFAULT_DIR_FD;
7008 char buffer[MAXPATHLEN];
7009 ssize_t length;
7010 PyObject *return_value = NULL;
7011 static char *keywords[] = {"path", "dir_fd", NULL};
(gdb) n
7013 memset(&path, 0, sizeof(path));
(gdb)
7014 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
(gdb)
7024 Py_BEGIN_ALLOW_THREADS
(gdb)
7026 if (dir_fd != DEFAULT_DIR_FD)
(gdb) p path
1ドル = {function_name = 0x0, argument_name = 0x0, nullable = 0, allow_fd = 0,
wide = 0x0, narrow = 0x805ec0f10 "/tmp/tmpko8vo_/baz", fd = -1, length = 18,
object = 0x805e30d60, cleanup = 0x805ec0ee0}
path.narrow and length are correct at that point.
(gdb) p dir_fd
2ドル = -100
(gdb) n
7024 Py_BEGIN_ALLOW_THREADS
(gdb) n
7026 if (dir_fd != DEFAULT_DIR_FD)
(gdb) n
7030 length = readlink(path.narrow, buffer, sizeof(buffer));
(gdb) n
7031 Py_END_ALLOW_THREADS
(gdb) p length
3ドル = 24
(gdb) p sizeof(buffer)
7ドル = 1024
(gdb) p buffer
9ドル = "/tmp/tmpko8vo_/foo000円000円000円000円000円000円ͤ\r001円\b000円000円000円000円000円000円000円??????A", '0円' <repeats 77 times>, "??203円000円\b000円000円000円?v???177円000円000円??A", '0円' <repeats 13 times>, "f023円J", '0円' <repeats 13 times>, "??A000円000円000円000円000円001円000円000円000円000円000円000円000円030円u???177円000円000円 u???177円000円000円RCJ000円000円000円000円000円000円001円000円000円000円000円000円000円??A000円000円000円000円000円?v???177円000円000円?(?005円\b000円000円0000円?L002円\b000円000円000円210円N?005円\b000円000円000円001円000円000円000円000円000円000円000円??A000円000円000円000円000円?"...
No idea why readlink is returning 24. Need to look into it more.
|
|||
| msg168804 - (view) | Author: Larry Hastings (larry) * (Python committer) | Date: 2012年08月21日 21:28 | |
I'll ask the obvious: was that an optimized build? Not that that explains the bug--but that might explain why "length" appeared to contain 24. It's hard to believe this is really an OS bug... |
|||
| msg168806 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月21日 21:32 | |
Hi Larry, Funnily enough, I just tried to step through a heavily hacked version of posix_readlink again, only to get gdb telling me I couldn't 'print' the variables I had added in. Turns out, `./configure --with-pydebug` on FreeBSD ends up with '-O2' being appended to CFLAGS some how. I've raised a separate issue for this: http://bugs.python.org/issue15748. |
|||
| msg168814 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月21日 22:28 | |
Well, bugger me, check this out:
import os
import stat
import tempfile
d = tempfile.mkdtemp()
src = os.path.join(d, 'foo')
dst = os.path.join(d, 'bar')
src_link = os.path.join(d, 'baz')
dst_link = os.path.join(d, 'qux')
sf = open(dst, 'w')
sf.write('foo')
sf.flush()
sf.close()
df = open(dst, 'w')
df.write('bar')
df.flush()
df.close()
os.symlink(src, src_link)
os.symlink(dst, dst_link)
os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
os.readlink(dst_link)
os.readlink(src_link)
Results of the last two calls:
>>> os.readlink(dst_link)
path 1: /tmp/tmpfz5v6h/qux, length 1: 18, buf 1: /tmp/tmpfz5v6h/bar
path 2: /tmp/tmpfz5v6h/qux, length 2: 18, buf 2: /tmp/tmpfz5v6h/bar
'/tmp/tmpfz5v6h/bar'
[73299 refs]
>>> os.readlink(src_link)
path 1: /tmp/tmpfz5v6h/baz, length 1: 24, buf 1: /tmp/tmpfz5v6h/foo
path 2: /tmp/tmpfz5v6h/baz, length 2: 24, buf 2: /tmp/tmpfz5v6h/foo
'/tmp/tmpfz5v6h/foo\x00\x00\x00\x00\x00\x00'
[73299 refs]
So, without the os.lchmod() call, the length is returned correctly. With it, it gets returned as 24. Looks like an OS bug.
|
|||
| msg168870 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月22日 11:41 | |
Hmmmmm... tested against other types of file systems and didn't see any issues. Tested manually against ZFS again: % ~/src/cpython/python /tmp/test_readlink.py temp dir: /mnt/t-zfs/trent/d_6i51 path 1: /mnt/t-zfs/trent/d_6i51/qux, length 1: 27, buf 1: /mnt/t-zfs/trent/d_6i51/bar path 2: /mnt/t-zfs/trent/d_6i51/qux, length 2: 27, buf 2: /mnt/t-zfs/trent/d_6i51/bar dst: /mnt/t-zfs/trent/d_6i51/bar path 1: /mnt/t-zfs/trent/d_6i51/baz, length 1: 24, buf 1: /mnt/t-zfs/trent/d_6i51/ path 2: /mnt/t-zfs/trent/d_6i51/baz, length 2: 24, buf 2: /mnt/t-zfs/trent/d_6i51/ src: /mnt/t-zfs/trent/d_6i51/ [47136 refs] This time, src got truncated by 3 characters back down to 24. (Instead of getting rounded up by 6 from 18->24 in the previous example.) Next step: replicate with a C snippet and ping the FreeBSD developers, I guess. |
|||
| msg168887 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2012年08月22日 14:27 | |
I don't understand if the issue comes from symlink() or readlink(). Can you reproduce the issue using commands on the command line? $ ln -s setup.py link `link' -> `setup.py' $ readlink link setup.py (You may need to test different length for filenames.) Do you only have the issue with ZFS, or with other file systems? |
|||
| msg168908 - (view) | Author: Larry Hastings (larry) * (Python committer) | Date: 2012年08月22日 21:09 | |
haypo: If a series of shell commands duplicated the problem, then okay, but I suspect the problem has to do with persistent state in the process and will only be reproducible with a C program. |
|||
| msg168971 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月24日 01:12 | |
Reproduced behaviour with test_readlink.sh. Sending an e-mail to freebsd-fs to see what they think. |
|||
| msg169007 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月24日 12:33 | |
Link to my freebsd-fs e-mail: http://lists.freebsd.org/pipermail/freebsd-fs/2012-August/014964.html |
|||
| msg169590 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年08月31日 23:16 | |
Turns out our unit test uncovered a very subtle corner-case bug in ZFS, requiring the following patch to FreeBSD:
a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
index 69374fb..7f61517 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
@@ -1695,6 +1695,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
ASSERT(action == SA_REPLACE);
SA_ADD_BULK_ATTR(attr_desc, j, attr,
locator, datastart, buflen);
+ length_idx++;
} else {
length = SA_REGISTERED_LEN(sa, attr);
if (length == 0) {
I guess the unit test should probably be patched to to skip the test IFF the underlying filesystem is ZFS and it exhibits the "length 24" problem. (Actually, detecting if the underlying filesystem is ZFS is non-trivial -- just testing for the "length 24" bug is probably sufficient.) I'll look into this later.
(According to Andriy Gapon (FreeBSD developer that came up with the patch), the bug is likely to affect all ZFS implementations since the beginning of time.)
|
|||
| msg169592 - (view) | Author: Larry Hastings (larry) * (Python committer) | Date: 2012年08月31日 23:23 | |
Could we work around it? Ignore the length we get back from readlink() and just measure the buffer ourselves? Or, if we wanted to be *really* paranoid, write a 0円 at the length they give us back and *then* strlen it. |
|||
| msg169620 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年09月01日 11:09 | |
Not really... the problem is that the chmod 0007 actually corrupts the ZFS metadata regarding the symlink by always setting the length to 24. Andriy did some debugging here: http://lists.freebsd.org/pipermail/freebsd-fs/2012-August/015005.html So, the link basically becomes invalid once the bug hits. Here's another option I just thought of: change the tests to use something other than 0007, then add another test specifically for this issue. |
|||
| msg169758 - (view) | Author: Trent Nelson (trent) * (Python committer) | Date: 2012年09月03日 12:56 | |
Link to discussion (initiated by Andriy) on zfs@lists.illumos.org: http://thread.gmane.org/gmane.os.illumos.zfs/69 |
|||
| msg221883 - (view) | Author: Mark Lawrence (BreamoreBoy) * | Date: 2014年06月29日 19:12 | |
Is any action needed here to take this forward, can it be closed as "out of date" or what? |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:57:34 | admin | set | github: 59953 |
| 2019年03月16日 00:08:09 | BreamoreBoy | set | nosy:
- BreamoreBoy |
| 2014年06月29日 19:12:04 | BreamoreBoy | set | nosy:
+ BreamoreBoy messages: + msg221883 versions: + Python 3.5, - Python 3.2, Python 3.3 |
| 2012年09月03日 12:56:38 | trent | set | messages: + msg169758 |
| 2012年09月01日 11:09:50 | trent | set | messages: + msg169620 |
| 2012年08月31日 23:23:50 | larry | set | messages: + msg169592 |
| 2012年08月31日 23:16:05 | trent | set | resolution: postponed messages: + msg169590 stage: needs patch |
| 2012年08月24日 12:33:39 | trent | set | messages: + msg169007 |
| 2012年08月24日 01:12:22 | trent | set | files:
+ test_readlink.sh messages: + msg168971 |
| 2012年08月22日 21:09:12 | larry | set | messages: + msg168908 |
| 2012年08月22日 14:27:29 | vstinner | set | nosy:
+ vstinner messages: + msg168887 |
| 2012年08月22日 11:41:44 | trent | set | messages: + msg168870 |
| 2012年08月21日 22:28:57 | trent | set | messages: + msg168814 |
| 2012年08月21日 21:33:00 | trent | set | messages: + msg168806 |
| 2012年08月21日 21:28:20 | larry | set | messages: + msg168804 |
| 2012年08月21日 20:46:02 | georg.brandl | set | nosy:
+ larry |
| 2012年08月21日 07:28:56 | trent | set | messages: + msg168749 |
| 2012年08月21日 02:26:57 | trent | create | |