Ticket UUID: | 2710920 | |||
Title: | [file tail] gives wrong result | |||
Type: | Bug | Version: | obsolete: 8.5.6 | |
Submitter: | jepler | Created on: | 2009-03-25 03:05:51 | |
Subsystem: | 36. Pathname Management | Assigned To: | dgp | |
Priority: | 9 Immediate | Severity: | ||
Status: | Closed | Last Modified: | 2009-03-28 05:02:23 | |
Resolution: | Fixed | Closed By: | dgp | |
Closed on: | 2009-03-27 19:20:43 | |||
Description: |
This problem occurs on a freshly built 8.5.6 (unmodified) on Ubuntu Hardy and is also seen on 8.5.3-2 on ubuntu jaunty alpha (ubuntu modified). The bug is not seen in 8.4.16-4ubuntu1 (ubuntu modified) on ubuntu hardy. In a specific scenario involving [glob] with a trailing slash, the resulting files are treated improperly by [file tail]. An attached script, which can be run by $ make shell SCRIPT=filetailbug.tcl demonstrates the problem on my system. Expected output: /bin bin Actual output: /bin {} | |||
User Comments: |
ferrieux added on 2009-03-28 05:02:23:
It hardly gets colder than that, eh ? dgp added on 2009-03-28 04:45:39: No; I like to limit the docs to things I like and want to keep. Internal details of dubious wisdom deserve writeups sometimes, but not in the docs. ferrieux added on 2009-03-28 04:30:10: Perhaps some chosen pieces of the very detailed and interesting description below could find a place in Filesystem.3 ? dgp added on 2009-03-28 02:20:43: allow_comments - 1 Fixed for 8.5.7 and 8.6b2 dgp added on 2009-03-28 02:04:53: File Added - 319929: 2710920.patch dgp added on 2009-03-28 01:47:57: [file dirname] suffers an analogous bug. dgp added on 2009-03-28 01:07:00: The mystery as to why the behavior is different whether or not the demo script is [source]d by relative or absolute name is complex, but explainable. When the file name is absolute, there's never any need to ask what the [pwd] value is in order to open and read that file. In this simple test script, it happens that nothing else needed to know that value either, so the value of [pwd] has never been determined. In the innermost part of the [glob] operation, we need to query the actual filesystem to determine what files exist. The routine TclpMatchInDirectory() in tclUnixFile.c does this, and it must construct the "native" name of the file to do so. It calls the routine Tcl_FSGetNativePath() to get that native name. This works its way back to the routine TclNativeCreateNativeRep() also in tclUnixFile.c. TNCNR has two branches depending on whether or not the [pwd] value is known to be in the native filesystem. In the case where we've never had reason to determine [pwd] up to that point, [pwd] is not known to be in the native filesystem, so a less efficient, safer path to generating the native name is taken by normalizing the path first. Normalizing the path converts it out of the intrep which triggers the bug. On the other hand, when the pathname of the demo script is relative, we had to compute [pwd] just to find and source the script, so we have the value and we know it's in the native filesystem, so within TNCNR we take a more efficient path to computing the native name which also preserves the intrep which is needed to demo the [file tail] bug. Perhaps more than you wanted to know, but I figured it should be written down somewhere. dgp added on 2009-03-27 04:20:26: Appears that the fix of 1972879 did not create this bug, but just exposed it, by permitting some otherwise untested codepaths to execute. Problem is that [file tail] on the PATHFLAGS !=0 intrep for path values is just broken when paths have trailing separators. dgp added on 2009-03-27 03:12:28: The fix for Bug 1972879 is to blame. dgp added on 2009-03-27 02:18:07: Bug introduced between 8.5.2 and 8.5.3. dgp added on 2009-03-27 01:19:48: Sorry, I was misled by --enable-shared builds. dgp added on 2009-03-27 00:58:50: Further testing indicates that Tcl 8.5.0 works, while 8.5.1 has the bug. jepler added on 2009-03-27 00:53:36: I'm glad you found how to reproduce it! I can confirm what dgp says: whether the script is given as an absolute path or not affects the output. dgp added on 2009-03-27 00:47:41: I can now reproduce the problem with Tcl 8.5.6: $ make shell SCRIPT=fff.tcl ... LD_LIBRARY_PATH="`pwd`:${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; \ TCL_LIBRARY="/home/dgp/cvs/tcl8.5.6/library"; export TCL_LIBRARY; \ ./tclsh fff.tcl /opt/ {} Note that a very similar attempt yields different results: $ make shell SCRIPT=~/fff.tcl ... LD_LIBRARY_PATH="`pwd`:${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; \ TCL_LIBRARY="/home/dgp/cvs/tcl8.5.6/library"; export TCL_LIBRARY; \ ./tclsh ~/fff.tcl /opt/ opt Same script in a different place and accessed via an absolute path. So inspired by that difference, try: $ make shell SCRIPT=`pwd`/fff.tcl ... LD_LIBRARY_PATH="`pwd`:${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; \ TCL_LIBRARY="/home/dgp/cvs/tcl8.5.6/library"; export TCL_LIBRARY; \ ./tclsh /home/dgp/cvs/tcl8.5.6/unix/fff.tcl /opt/ opt jepler added on 2009-03-26 07:08:33: I failed to correctly minimize the test case in my original submission. Please see the attached 'fff.tcl' instead of the original attachment. $ cat fff.tcl proc f {} { set d [glob -nocomplain /*/] set d [lindex $d 0] #set d [format %s $d] # uncommenting this line makes both 8.4 and 8.5 work puts stderr [list $d [file tail $d]] } f $ make shell SCRIPT=fff.tcl LD_LIBRARY_PATH="`pwd`:${LD_LIBRARY_PATH}"; export LD_LIBRARY_PATH; \ TCL_LIBRARY="/tmp/tcl8.5.6/library"; export TCL_LIBRARY; \ ./tclsh fff.tcl /mnt/ {} $ jepler added on 2009-03-26 07:06:19: File Added - 319626: fff.tcl jepler added on 2009-03-26 07:05:49: File Deleted - 319464: jepler added on 2009-03-25 10:07:16: I am not familiar with the tcl path object, but I attempted to generate some useful debugging information. I found that the 'normPathPtr' is an empty string, and that TclPathpart returns normPathPtr, leading to the result I am seeing. Perhaps the problem is occurring earlier at the point where this path object is constructed? Breakpoint 3, TclPathPart (interp=0x606400, pathPtr=0x62aa00, portion=TCL_PATH_TAIL) at /tmp/tcl8.5.6/unix/../generic/tclPathObj.c:596 596const char *rest = TclGetString(fsPathPtr->normPathPtr); (gdb) print fsPathPtr->translatedPathPtr->bytes $32 = 0x636be0 "/bin" (gdb) print fsPathPtr->normPathPtr->bytes $33 = 0x7f2ed6902b48 "" (gdb) next 598if (strchr(rest, '/') != NULL) { (gdb) 601if (tclPlatform == TCL_PLATFORM_WINDOWS (gdb) 605Tcl_IncrRefCount(fsPathPtr->normPathPtr); (gdb) 606return fsPathPtr->normPathPtr; (gdb) 747} (gdb) jepler added on 2009-03-25 10:05:52: File Added - 319464: filetailbug.tcl |