Bug #8810

GDBM.open内で処理がブロックしたらTimeout.timeout が効かない

Added by Naohisa Goto 8 months ago. Updated 8 months ago.

[ruby-dev:47652]
Status:Open
Priority:Normal
Assignee:-
Category:ext
Target version:-
ruby -v:- Backport:1.9.3: UNKNOWN, 2.0.0: UNKNOWN

Description

GDBM.open内で処理がブロックした場合にTimeout.timeoutが効きません。

再現方法は、Solarisにて、以下のようにGDBMをオープンしたままにして、

$ ruby -r gdbm -e 'db = GDBM.open("/var/tmp/tmpdb"); gets'

同一マシンで別のシェルで

$ ruby -r gdbm -r timeout -e 'Timeout.timeout(5) { db = GDBM.open("/var/tmp/tmpdb") }'

を実行しても、タイムアウトすることなく後者のGDBM.openがブロックし続けて終わりません。

Solarisだけでなく、Linux上にて、以下のように無理やりflockを使わないようconfigureしてmakeしたlibgdbm.soを使用した場合でも同様に再現しました。

$ wget ftp://ftp.gnu.org/gnu/gdbm/gdbm-1.10.tar.gz
$ tar xvf gdbm-1.10.tar.gz
$ cd gdbm-1.10
$ ./configure --prefix=/home/xxxxx/gdbm accvfuncflock=no
$ make
$ make install
$ LD
PRELOAD=/home/xxxxx/gdbm/lib/libgdbm.so ruby -r gdbm -e 'db = GDBM.open("/var/tmp/tmpdb"); gets'
(別のシェルにて)
$ LD_PRELOAD=/home/xxxxx/gdbm/lib/libgdbm.so ruby -r gdbm -r timeout -e 'Timeout.timeout(5) { db = GDBM.open("/var/tmp/tmpdb") }'


Related issues

Related to ruby-trunk - Bug #8790: r41424 以降、Solaris と gdbm 1.1.10 にて TestGDBM#test_s_open_l... Open 08/16/2013

History

#1 Updated by Naohisa Goto 8 months ago

  • Subject changed from SolarisでGDBM.open内で処理がブロックしたらTimeout.timeout が効かない to GDBM.open内で処理がブロックしたらTimeout.timeout が効かない

#2 Updated by Motohiro KOSAKI 8 months ago

2013/8/22 ngoto (Naohisa Goto) ngotogenome@gmail.com:

Issue #8810 has been reported by ngoto (Naohisa Goto).


Bug #8810: SolarisでGDBM.open内で処理がブロックしたらTimeout.timeout が効かない
https://bugs.ruby-lang.org/issues/8810

Author: ngoto (Naohisa Goto)
Status: Open
Priority: Normal
Assignee:
Category: ext
Target version:
ruby -v: -
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN

GDBM.open内で処理がブロックした場合にTimeout.timeoutが効きません。

再現方法は、Solarisにて、以下のようにGDBMをオープンしたままにして、

$ ruby -r gdbm -e 'db = GDBM.open("/var/tmp/tmpdb"); gets'

同一マシンで別のシェルで

$ ruby -r gdbm -r timeout -e 'Timeout.timeout(5) { db = GDBM.open("/var/tmp/tmpdb") }'

を実行しても、タイムアウトすることなく後者のGDBM.openがブロックし続けて終わりません。

Solarisだけでなく、Linux上にて、以下のように無理やりflockを使わないようconfigureしてmakeしたlibgdbm.soを使用した場合でも同様に再現しました。

ちらっと見たのですが、これはgdbmを直さないとどうしようもないような
以下コメント付きソースの抜粋。

int
gdbmlockfile (GDBMFILE dbf)
{
#if HAVEFCNTLLOCK
struct flock fl;
#endif
int lock_val = -1;

#if HAVEFLOCK // 最初にflockを試す
if (dbf->read
write == GDBMREADER)
lock
val = flock (dbf->desc, LOCKSH + LOCKNB); // この時はLOCKNB使う
else
lock
val = flock (dbf->desc, LOCKEX + LOCKNB);

if ((lockval == -1) && (errno == EWOULDBLOCK))
{
dbf->lock
type = LOCKINGNONE;
return lock
val;
}
else if (lockval != -1)
{
dbf->lock
type = LOCKINGFLOCK;
return lock
val;
}
#endif

// 次に lockf ためす
#if HAVELOCKF
/* Mask doesn't matter for lockf. */
lock
val = lockf (dbf->desc, FLOCK, (offt)0L); // なぜか FTLOCK つけない
if ((lock
val == -1) && (errno == EDEADLK))
{
dbf->locktype = LOCKINGNONE;
return lockval;
}
else if (lock
val != -1)
{
dbf->locktype = LOCKINGLOCKF;
return lock_val;
}
#endif

// 最後に fcntl ためす
#if HAVEFCNTLLOCK
/* If we're still here, try fcntl. */
if (dbf->readwrite == GDBMREADER)
fl.ltype = FRDLCK;
else
fl.ltype = FWRLCK;
fl.lwhence = SEEKSET;
fl.lstart = fl.llen = (offt)0L;
lock
val = fcntl (dbf->desc, FSETLK, &fl); // こんどはFSETLKなので待たない

if (lockval != -1)
dbf->lock
type = LOCKING_FCNTL;
#endif

if (lockval == -1)
dbf->lock
type = LOCKINGNONE;
return lock
val;
}

Also available in: Atom PDF