[cfe-dev] Clang violates the mkstemp() contract?
Török Edwin
edwintorok at gmail.com
Wed Jul 14 12:09:17 PDT 2010
On Wed, 14 Jul 2010 16:43:23 +0200
Kees van Reeuwijk <reeuwijk at few.vu.nl> wrote:
> Hello,
>
>
> My apologies for the half-researched problem, but unfortunately I
> don't have the time to verify this properly, and this looks like a
> subtle bug that might bite other people.
>
> If on Minix I run clang on two source files:
>
> clang -v a.c b.c
>
> compilation fails with the following output (The 'entering ...' and
> 'Created ...' are from debugging code I added to Path::makeUnique()):
>
> ---------------
> clang version 2.8 (trunk 108237)
> Target: i386-pc-minix
> Thread model: posix
> entering HAVE_MKSTEMP section
> Created mktemp temp filename '/tmp/cc-002440'
> entering HAVE_MKSTEMP section
> Created mktemp temp filename '/tmp/cc-002440'
> entering HAVE_MKSTEMP section
> Created mktemp temp filename '/tmp/cc-002440'
> entering HAVE_MKSTEMP section
> Created mktemp temp filename '/tmp/cc-002440'
> "/usr/llvm/bin/clang" -cc1 -triple i386-pc-minix -S -disable-free
> -main-file-name a.c -mrelocation-model static -mdisable-fp-elim
> -mconstructor-aliases -target-cpu pentium4 -v
> -resource-dir /lib/clang/2.8 -ferror-limit 19 -fmessage-length 0
> -fgnu-runtime -fdiagnostics-show-option -o /tmp/cc-002440.s -x c a.c
> clang -cc1 version 2.8 based upon llvm 2.8svn hosted on i386-pc-minix
> ignoring nonexistent directory "/lib/clang/2.8/include" #include
> "..." search starts here: #include <...> search starts
> here: /usr/local/include /usr/include
> End of search list.
> "/usr/gnu/bin/gas" -o /tmp/cc-002440.o /tmp/cc-002440.s
> "/usr/llvm/bin/clang" -cc1 -triple i386-pc-minix -S -disable-free
> -main-file-name b.c -mrelocation-model static -mdisable-fp-elim
> -mconstructor-aliases -target-cpu pentium4 -v
> -resource-dir /lib/clang/2.8 -ferror-limit 19 -fmessage-length 0
> -fgnu-runtime -fdiagnostics-show-option -o /tmp/cc-002440.s -x c b.c
> clang -cc1 version 2.8 based upon llvm 2.8svn hosted on i386-pc-minix
> ignoring nonexistent directory "/lib/clang/2.8/include" #include
> "..." search starts here: #include <...> search starts
> here: /usr/local/include /usr/include
> End of search list.
> "/usr/gnu/bin/gas" -o /tmp/cc-002440.o /tmp/cc-002440.s
> "/usr/gnu/bin/gld" -o
> a.out /usr/gnu/lib/crtso.o /tmp/cc-002440.o /tmp/cc-002440.o -lc
> -lgcc -L/usr/gnu/lib
> -L/usr/gnu/lib/gcc/i686-pc-minix/4.4.3 /usr/gnu/lib/libend.a /tmp/cc-002440.o:/tmp/cc-002440.o:(.text+0x0):
> multiple definition of
> `main' /tmp/cc-002440.o:/tmp/cc-002440.o:(.text+0x0): first defined
> here /tmp/cc-002440.o:/tmp/cc-002440.o:(.text+0x28): undefined
> reference to `fA' /tmp/cc-002440.o:/tmp/cc-002440.o:(.text+0x28):
> undefined reference to `fA' error: linker command failed with exit
> code 1 (use -v to see invocation) ---------------
>
> The compilation fails because for the compilation of both a.c and b.c
> the same temporary files are used, meaning that the .o file of a.c is
> overwritten when the .o file for b.c is generated, and the loader
> simply gets the same .o file twice.
>
> As expected, this compilation succeeds if -save-temps is added.
>
> After some digging around I strongly suspect that someone has
> overlooked the fact that mktemp() and mkstemp() may well return the
> same filename twice. If you remove a file that was created by
> mkstemp(), or if you never create the file that mas generated for you
> by mktemp(), these functions may well return the same filename the
> next time they are invoked with the same template. In fact, in
> Driver::GetTemporaryPath() I see the code:
>
> // FIXME: Grumble, makeUnique sometimes leaves the file around!?
> PR3837. P.eraseFromDisk(false, 0);
The file should probably not be removed at all. If there is concern
that the file stays there after process exit, it should be added to
removeFileOnSignal.
>
> Which seems to confirm that an unwarranted assumption is made.
>
> The reason this works on many platforms is because there the unique
> filename is generated by first attempting to use a name based on a
> random number. If a file with that name exists, the name is then
> modified to avoid existing names. However, on Minix the first attempt
> uses the process id, so you'll always get the same temporary filename
> if the previous ones do not exist (any more), on other platforms that
> is far less likely (but not impossible).
Sounds like mkstemp() on Minix is fairly predictable then.
Best regards,
--Edwin
More information about the cfe-dev
mailing list