Forum: Ruby-dev [ruby-trunk - Bug #8810][Open] SolarisでGDBM.open内で処理がブロックしたらTimeout.timeout が効かない

205ca9566e14fb669ed977cae5af88e0?d=identicon&s=25 ngoto (Naohisa Goto) (Guest)
on 2013-08-22 17:28
(Received via mailing list)
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を使用した場合でも同様に再現しました。

 $ 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 ac_cv_func_flock=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") }'
205ca9566e14fb669ed977cae5af88e0?d=identicon&s=25 ngoto (Naohisa Goto) (Guest)
on 2013-08-22 17:30
(Received via mailing list)
Issue #8810 has been updated by ngoto (Naohisa Goto).

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


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

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を使用した場合でも同様に再現しました。

 $ 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 ac_cv_func_flock=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") }'
02da662c083396641da96c1d32fc86ed?d=identicon&s=25 KOSAKI Motohiro (Guest)
on 2013-08-24 01:25
(Received via mailing list)
2013/8/22 ngoto (Naohisa Goto) <ngotogenome@gmail.com>:
> Assignee:
>  $ ruby -r gdbm -e 'db = GDBM.open("/var/tmp/tmpdb"); gets'
>
> $BF10l%^%7%s$GJL$N%7%'%k$G(B
>
>  $ ruby -r gdbm -r timeout -e 'Timeout.timeout(5) { db =
GDBM.open("/var/tmp/tmpdb") }'
>
>
$B$r<B9T$7$F$b!"%?%$%`%"%&%H$9$k$3$H$J$/8e<T$N(BGDBM.open$B$,%V%m%C%/$7B3$1$F=*$o$j$^$;$s!#(B
>
>
Solaris$B$@$1$G$J$/!"(BLinux$B>e$K$F!"0J2<$N$h$&$KL5M}$d$j(Bflock$B$r;H$o$J$$$h$&(Bconfigure$B$7$F(Bmake$B$7$?(Blibgdbm.so$B$r;HMQ$7$?>l9g$G$bF1MM$K:F8=$7$^$7$?!#(B

$B$A$i$C$H8+$?$N$G$9$,!"$3$l$O(Bgdbm$B$rD>$5$J$$$H$I$&$7$h$&$b$J$$$h$&$J(B
$B0J2<%3%a%s%HIU$-%=!<%9$NH4?h!#(B

int
_gdbm_lock_file (GDBM_FILE dbf)
{
#if HAVE_FCNTL_LOCK
  struct flock fl;
#endif
  int lock_val = -1;

#if HAVE_FLOCK  // $B:G=i$K(Bflock$B$r;n$9(B
  if (dbf->read_write == GDBM_READER)
    lock_val = flock (dbf->desc, LOCK_SH + LOCK_NB); //
$B$3$N;~$O(BLOCK_NB$B;H$&(B
  else
    lock_val = flock (dbf->desc, LOCK_EX + LOCK_NB);

  if ((lock_val == -1) && (errno == EWOULDBLOCK))
    {
      dbf->lock_type = LOCKING_NONE;
      return lock_val;
    }
  else if (lock_val != -1)
    {
      dbf->lock_type = LOCKING_FLOCK;
      return lock_val;
    }
#endif

// $B<!$K(B lockf $B$?$a$9(B
#if HAVE_LOCKF
  /* Mask doesn't matter for lockf. */
  lock_val = lockf (dbf->desc, F_LOCK, (off_t)0L); // $B$J$<$+(B F_TLOCK
$B$D$1$J$$(B
  if ((lock_val == -1) && (errno == EDEADLK))
    {
      dbf->lock_type = LOCKING_NONE;
      return lock_val;
    }
  else if (lock_val != -1)
    {
      dbf->lock_type = LOCKING_LOCKF;
      return lock_val;
    }
#endif

// $B:G8e$K(B fcntl $B$?$a$9(B
#if HAVE_FCNTL_LOCK
  /* If we're still here, try fcntl. */
  if (dbf->read_write == GDBM_READER)
    fl.l_type = F_RDLCK;
  else
    fl.l_type = F_WRLCK;
  fl.l_whence = SEEK_SET;
  fl.l_start = fl.l_len = (off_t)0L;
  lock_val = fcntl (dbf->desc, F_SETLK, &fl); //
$B$3$s$I$O(BF_SETLK$B$J$N$GBT$?$J$$(B

  if (lock_val != -1)
    dbf->lock_type = LOCKING_FCNTL;
#endif

  if (lock_val == -1)
    dbf->lock_type = LOCKING_NONE;
  return lock_val;
}
This topic is locked and can not be replied to.