mishimaの日記: 先日の困ったなぁ…の解決策
libc にパッチを当ててみた。とりあえずうまく動いてはいるようだ。こんな感じの内容だ。
--- sysdeps/unix/sysv/linux/openat.c.orig 2008-02-14 16:43:27.000000000 +0900
+++ sysdeps/unix/sysv/linux/openat.c 2008-02-14 16:45:38.000000000 +0900
@@ -87,13 +87,17 @@
INTERNAL_SYSCALL_DECL (err);
int res;
+ int o_cloexec;
#ifdef __NR_openat
# ifndef __ASSUME_ATFCTS
if (__have_atfcts >= 0)
# endif
{
+ o_cloexec = oflag & O_CLOEXEC;
+ oflag &= ~O_CLOEXEC;
res = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode);
+ if( res >= 0 && o_cloexec ) fcntl(res, F_SETFD, FD_CLOEXEC);
# ifndef __ASSUME_ATFCTS
if (res == -1 && errno == ENOSYS)
@@ -126,6 +130,8 @@
file = buf;
}
+ o_cloexec = oflag & O_CLOEXEC;
+ oflag &= ~O_CLOEXEC;
res = INTERNAL_SYSCALL (open, err, 3, file, oflag, mode);
if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
@@ -133,6 +139,7 @@
__atfct_seterrno (INTERNAL_SYSCALL_ERRNO (res, err), fd, buf);
res = -1;
}
+ if( res >= 0 && o_cloexec ) fcntl(res, F_SETFD, FD_CLOEXEC);
return res;
#endif
--- sysdeps/unix/sysv/linux/not-cancel.h.orig 2008-02-15 13:33:39.000000000 +0900
+++ sysdeps/unix/sysv/linux/not-cancel.h 2008-02-15 13:39:31.000000000 +0900
@@ -22,10 +22,21 @@
#include <sysdep.h>
/* Uncancelable open. */
+static int __internal_open_not_cancel( const char* name, int flags, mode_t mode ){
+ int r = INLINE_SYSCALL ( open, 3, name, flags&~O_CLOEXEC, mode );
+ if( r >= 0 && flags&O_CLOEXEC ) fcntl( res, F_SETFD, FD_CLOEXEC );
+ return r;
+}
+static int __internal_open_not_cancel_2( const char* name, int flags ){
+ int r = INLINE_SYSCALL ( open, 2, name, flags&~O_CLOEXEC );
+ if( r >= 0 && flags&O_CLOEXEC ) fcntl( res, F_SETFD, FD_CLOEXEC );
+ return r;
+}
+
#define open_not_cancel(name, flags, mode) \
- INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode))
+ __internal_open_not_cancel ( (name), (flags), (mode) )
#define open_not_cancel_2(name, flags) \
- INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
+ __internal_open_not_cancel_2 ( (name), (flags) )
/* Uncancelable openat. */
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
--- sysdeps/unix/sysv/linux/open64.c.orig 2008-02-15 13:36:54.000000000 +0900
+++ sysdeps/unix/sysv/linux/open64.c 2008-02-15 13:45:59.000000000 +0900
@@ -38,12 +38,16 @@
va_end (arg);
}
- if (SINGLE_THREAD_P)
- return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+ if (SINGLE_THREAD_P){
+ int r = INLINE_SYSCALL (open, 3, file, (oflag&~O_CLOEXEC)|O_LARGEFILE, mode);
+ if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+ return r;
+ }
int oldtype = LIBC_CANCEL_ASYNC ();
- int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+ int result = INLINE_SYSCALL (open, 3, file, (oflag&~O_CLOEXEC)|O_LARGEFILE, mode);
+ if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
LIBC_CANCEL_RESET (oldtype);
@@ -63,12 +67,16 @@
if (oflag & O_CREAT)
__fortify_fail ("invalid open64 call: O_CREAT without mode");
- if (SINGLE_THREAD_P)
- return INLINE_SYSCALL (open, 2, file, oflag | O_LARGEFILE);
+ if (SINGLE_THREAD_P){
+ int r = INLINE_SYSCALL (open, 2, file, (oflag&~O_CLOEXEC)|O_LARGEFILE);
+ if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+ return r;
+ }
int oldtype = LIBC_CANCEL_ASYNC ();
- int result = INLINE_SYSCALL (open, 2, file, oflag | O_LARGEFILE);
+ int result = INLINE_SYSCALL (open, 2, file, (oflag&~O_CLOEXEC)|O_LARGEFILE);
+ if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
LIBC_CANCEL_RESET (oldtype);
--- sysdeps/unix/sysv/linux/open.c.orig 2008-02-15 21:26:30.000000000 +0900
+++ sysdeps/unix/sysv/linux/open.c 2008-02-15 20:03:54.000000000 +0900
@@ -0,0 +1,57 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sysdep-cancel.h>
+
+int __open_nocancel (const char *file, int oflag, ...)
+{
+ int mode = 0;
+
+ if (oflag & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, oflag);
+ mode = va_arg (arg, int);
+ va_end (arg);
+ }
+
+ int result = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+ if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
+
+ return result;
+}
+
+int __libc_open (const char *file, int oflag, ...)
+{
+ int mode = 0;
+
+ if (oflag & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, oflag);
+ mode = va_arg (arg, int);
+ va_end (arg);
+ }
+
+ if (SINGLE_THREAD_P){
+ int r = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+ if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+ return r;
+ }
+
+ int oldtype = LIBC_CANCEL_ASYNC ();
+
+ int result = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+ if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
+
+ LIBC_CANCEL_RESET (oldtype);
+
+ return result;
+}
+libc_hidden_def (__libc_open)
+
+weak_alias (__libc_open, __open)
+libc_hidden_weak (__open)
+weak_alias (__libc_open, open)
+
で、これをこんな風に適用してみた。
% apt-get source libc6
% cd glibc-2.7
% cp ABOVE_PATCH_FILE debian/patches/i386/local-O_CLOEXEC.diff
% echo "i386/local-O_CLOEXEC.diff -p0" >> debian/patches/series
% dpkg-buildpackage
debuild だとうまくいかないので dpkg-buildpackage で。ちゃんとパッケージの形にすればいいんだろうが、面倒くさいので今のところは放置しときます。
英語圏の人のために別エントリを立ててみたが、不得意なのはわかっているので気にしないように。
先日の困ったなぁ…の解決策 More ログイン