[ruby-dev:46834] Re: [ruby-changes:26632] yugui:r38683 (trunk): * io.c (rb_cloexec_fcntl_dupfd): Fix failures in

From: Tanaka Akira <akr@...>
Date: 2013-01-05 03:28:20 UTC
List: ruby-dev #46834
2013/1/4 yugui <ko1@atdot.net>:

> @@ -318,8 +318,10 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd https://github.com/ruby/ruby/blob/trunk/io.c#L318
>      else {
>          ret = fcntl(fd, F_DUPFD, minfd);
>      }
> -#else
> +#elif defined(HAVE_FCNTL) && !defined(__native_client__)
>      ret = fcntl(fd, F_DUPFD, minfd);
> +#else
> +    ret = dup2(fd, minfd);
>  #endif
>      if (ret == -1) return -1;
>      rb_maygvl_fd_fix_cloexec(ret);

えぇと、dup2(oldfd, newfd) と fcntl(oldfd, F_DUPFD, newfd) は newfd が使用中だった時の挙動が違うので、
rb_cloexec_fcntl_dupfd の実装として dup2 を使うのはうまくありません。

dup2 は newfd が使用中でもそこに複製するのに対し、F_DUPFD は newfd 以上で未使用の fd を探して複製します。
なので、dup2 を使ってしまうと、使用中の fd を潰してしまいます。

ではどうすれば F_DUPFD を実現できるかというと、
dup を繰り返して newfd 以上のが見つかったらそれを残して close する、
という方法があります。

前に書いた記憶があるんだけど見つからない...
たしか、任意数の fd を覚えておくために再帰を使っていたような気がします。
-- 
[田中 哲][たなか あきら][Tanaka Akira]

In This Thread

Prev Next