Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Can somebody confirm possible bug writing to (and deleting) files created with file tempfile

43 views
Skip to first unread message

jemptymethod

unread,
Feb 11, 2018, 8:50:04 AM2/11/18
to
I've only been back at programming in Tcl/Tk for less than 24 hours so don't want to jump the gun by reporting a bug so might like another set of eyeballs on this. My problem is I cannot write to a temp file created with "file tempfile" using either tclkit867.exe or the latest ActiveState Tcl ($tcl_version does not give a minor number, just 8.6) on a Windows 7 Professional system. What I'm describing below chiefly pertains to my usage with the tclkit (on cygwin) as that is most important to me as I want to eventually package things up in a starkit

What I'm trying to do is write stderr to a tmpfile, this seems easier than writing it to a variable (not all my Windows users will have cygwin/bash) though if anybody has any pointers on that I'm all ears. The following:

file tempfile stdErrFile
exec git status --porcelain 2>$stdErrFile

Results in

couldn't write file "C:/opt/cygwin/exe/tmp/TCL23058.TMP": permission denied (Got a similar error using ActiveState Tcl 8.6 pointed at a file in a different directory though)

So I did an ls on the file and it's output is as follows

-rwxr-xr-x 1 George None 0 Feb 11 07:35 TCL23058.TMP

Ok so the write bits for group and other are not set so it makes sense that my script can't write to it, but on the other hand it makes no sense that I can't write to a temp file. However I did notice the executable bits set for everybody and therefore tried to write my own tempfile proc still relying on "file tempfile" to determine the temporary directory, with the hopes that I could then open a temporary file in that directory for reading/writing. Before I even get that far though....

proc tempFile {} {
upvar #0 tempDir tempDir
if {$tempDir eq ""} {
file tempfile tmpFile
set tempDir [file dirname $tmpFile]
file delete $tmpFile ;# fails :(
}
return [file join $tempDir "grumble.[clock seconds].txt"]
}

You can see from the comment though that I can't delete even delete the temporary file created with "file tempfile". So I guess I'll give tcllib/fileutils a shot, however, has anybody experienced this themselves? Can I possibly get someone to try before I file a bug report?

Thanks in advance....George

Ashok

unread,
Feb 11, 2018, 9:28:11 AM2/11/18
to
The file tempfile command creates a temp file and *also returns a
writable channel handle to that file*. The fact that the file is open
means that other processes (git in your case) cannot write to it. Before
execing git, you need to close the channel handle returned, something like

close [file tempfile stdErrFile]
exec git status 2>$stdErrFile

Alternatively, you can also pass the temp file channel descriptor.
Something like

set fd [file tempfile]
exec git status 2>@$fd
seek $fd 0; # Go back to beginning of file
read $fd; # and read error messages
close $fd

Here the temp file will be automatically deleted on the close $fd
because the second stdErrFile arg to [file tempfile] is not specified
(although you could if you wanted to preserve the file). Whether you
want this or not depends on your use case.

The second method happens to have the advantage that the temp file will
not be accidentally removed by some disk cleaner before the child
process is exec-ed. Very low probability of course.

/Ashok

jemptymethod

unread,
Feb 11, 2018, 9:29:45 AM2/11/18
to
On Sunday, February 11, 2018 at 7:50:04 AM UTC-6, jemptymethod wrote:
> I've only been back at programming in Tcl/Tk for less than 24 hours so don't want to jump the gun by reporting a bug so might like another set of eyeballs on this. My problem is I cannot write to a temp file created with "file tempfile" using either tclkit867.exe or the latest ActiveState Tcl

I'm really starting to lean toward the distinct possibility that this is indeed a bug. Because, when using my home-rolled tempFile proc, disregarding that it cannot delete the file it creates with "file tempfile" for gleaning the temporary directory, the following does *not* result in an error:

set tempFile [tempFile]
set fh [open $tempFile w+]
catch {exec git status --porcelain 2>$tempFile}
#etc

jemptymethod

unread,
Feb 11, 2018, 9:31:09 AM2/11/18
to
Let me try Ashok's suggestion before jumping the gun....

jemptymethod

unread,
Feb 11, 2018, 10:13:45 AM2/11/18
to
On Sunday, February 11, 2018 at 8:28:11 AM UTC-6, Ashok wrote:
> The file tempfile command creates a temp file and *also returns a
> writable channel handle to that file*. The fact that the file is open
> means that other processes (git in your case) cannot write to it. Before
> execing git, you need to close the channel handle returned, something like
>
> close [file tempfile stdErrFile]
> exec git status 2>$stdErrFile
>
> Alternatively, you can also pass the temp file channel descriptor.
> Something like
>
> set fd [file tempfile]
> exec git status 2>@$fd
> seek $fd 0; # Go back to beginning of file
> read $fd; # and read error messages
> close $fd

Went with the second one, worked like a charm, and thanks for the explanation

George

Rich

unread,
Feb 11, 2018, 10:28:51 AM2/11/18
to
jemptymethod <jempty...@gmail.com> wrote:
> file tempfile stdErrFile
> exec git status --porcelain 2>$stdErrFile
>
> Results in
>
> couldn't write file "C:/opt/cygwin/exe/tmp/TCL23058.TMP": permission
> denied (Got a similar error using ActiveState Tcl 8.6 pointed at a
> file in a different directory though)

As expected on a winblows system.

Note this, critical, detail in the tempfile portion of the file
manpage:

file tempfile ?nameVar? ?template?
Creates a temporary file and *returns a read-write
channel opened* on that file.

Winblows will not allow a second process to write to, or delete, a file
that is open by a different process.

You want to either:

1) use exec's 'redirect to a file descriptor' mode (see the 2>@
operator definition in the exec man page

2) close the open file descriptor before you use the "redirect to
file" mode (the 2> you are currently using)

Rich

unread,
Feb 11, 2018, 10:29:26 AM2/11/18
to
jemptymethod <jempty...@gmail.com> wrote:
> On Sunday, February 11, 2018 at 7:50:04 AM UTC-6, jemptymethod wrote:
>> I've only been back at programming in Tcl/Tk for less than 24 hours
>> so don't want to jump the gun by reporting a bug so might like
>> another set of eyeballs on this. My problem is I cannot write to a
>> temp file created with "file tempfile" using either tclkit867.exe or
>> the latest ActiveState Tcl
>
> I'm really starting to lean toward the distinct possibility that this
> is indeed a bug.

Well, yes, it is a bug, but it is a bug in winblows, not in Tcl.

> Because, when using my home-rolled tempFile proc, disregarding that
> it cannot delete the file it creates with "file tempfile" for
> gleaning the temporary directory, the following does *not* result in
> an error:
>
> set tempFile [tempFile]
> set fh [open $tempFile w+]
> catch {exec git status --porcelain 2>$tempFile}

Because you 'catch' the error (and then proceed to drop the error data
on the floor). This above should error out identically, except you
never see the error at the Tcl level because of the catch.

Ashok

unread,
Feb 11, 2018, 11:46:56 PM2/11/18
to
On 2/11/2018 8:59 PM, Rich wrote:
> Well, yes, it is a bug, but it is a bug in winblows, not in Tcl.
>

Well, I wouldn't say that. Windows does allow you to specify whether an
open file should be accessible (and mode) from other processes or not.
Tcl chooses to make it inaccessible which in my mind is the right default.

/Ashok
0 new messages