Bug #8816

Tempfile.new may return the same name for parallel calls

Added by Hleb Valoshka 8 months ago. Updated 8 months ago.

[ruby-core:56795]
Status:Third Party's Issue
Priority:Normal
Assignee:-
Category:-
Target version:-
ruby -v:ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux] Backport:1.9.3: UNKNOWN, 2.0.0: UNKNOWN

Description

Two simultaneous call to Tempfile.new may return the same name. This may lead
to race conditions.

There some examples of such races (unix socket can't be unlinked because it was
unlinked by another test case):

https://buildd.debian.org/status/fetch.php?pkg=ruby-kgio&arch=ia64&ver=2.8.0-1&stamp=1376819434
https://buildd.debian.org/status/fetch.php?pkg=ruby-kgio&arch=kfreebsd-i386&ver=2.8.0-1&stamp=1376820662

History

#1 Updated by Akira Tanaka 8 months ago

  • Status changed from Open to Third Party's Issue

Tempfile.new creates a normal file, not unix socket.
So, your report is questionable.

Note that Tempfile uses O_EXCL to exclusive file creation.
If it doesn't work, it is a problem of kernel.

I checked kgio.
It seems the temporary file created by Tempfile.new is removed and
unix socket is created the name.

http://bogomips.org/kgio.git/tree/test/test_unix_connect.rb :

class TestKgioUnixConnect < Test::Unit::TestCase

def setup
  tmp = Tempfile.new('kgio_unix')
  @path = tmp.path
  File.unlink(@path)
  tmp.close rescue nil
  @srv = Kgio::UNIXServer.new(@path)
  @addr = Socket.pack_sockaddr_un(@path)
end

The race condition should be solved by application.
Because another process may creates the file between unlink and unix socket creation.
Tempfile cannot do anything between them because Tempfile methods are not running at that time.

#2 Updated by Eric Wong 8 months ago

"akr (Akira Tanaka)" akr@fsij.org wrote:

http://bogomips.org/kgio.git/tree/test/test_unix_connect.rb :

class TestKgioUnixConnect < Test::Unit::TestCase

def setup
  tmp = Tempfile.new('kgio_unix')
  @path = tmp.path
  File.unlink(@path)
  tmp.close rescue nil
  @srv = Kgio::UNIXServer.new(@path)
  @addr = Socket.pack_sockaddr_un(@path)
end

The race condition should be solved by application.

Agreed (kgio maintainer here).

Hleb: can you send me a patch to retry on bind failure?

I'm a little surprised it happens since $$ is in the Tempfile name and
the tests are not multi-threaded (but optionally multi-process).

Because another process may creates the file between unlink and unix
socket creation.
Tempfile cannot do anything between them because Tempfile methods are
not running at that time.

Right. I do this often in test cases, but I'm lazy and have never hit
a problem even though I know it's there :x

#3 Updated by Nobuyoshi Nakada 8 months ago

Tempfile.create may help you to create unique file name, but it's your task to guarantee that it doesn't conflict.

Also available in: Atom PDF