[#38919] Ruby 1.8.1 preview4 — matz@... (Yukihiro Matsumoto)

Hi,

44 messages 2003/12/22
[#38921] Re: Ruby 1.8.1 preview4 — "NAKAMURA, Hiroshi" <nakahiro@...> 2003/12/22

Hi, all,

[ruby-list:38899] Re: pty problem

From: nobu.nakada@...
Date: 2003-12-12 08:19:03 UTC
List: ruby-list #38899
なかだです。

At Fri, 12 Dec 2003 12:32:44 +0900,
Takahiro Kambe wrote:
> > > execvp の直前で timer を clear するよう以下のような修正をしたところ、
> > > RuntimeError が上がる現象がおさまるようになりました。
> > 
> > 1.8では、rb_f_exec()、つまりKernel#execを使うように修正されてい
> > ます。1.6にバックポートしてもいいのですが、もう1.6.9は出ないと
> > いうことになっていますから、1.8への移行をお勧めします。
> 1.6でも、単純にrb_f_exec()を使うように直せば済むのでしょうか。

1.6だとrb_f_exec()はstaticなので、単純には無理ですね。

> 1.6.9は出なくとも、CVSの1.6のブランチで確実な修正がされていると嬉しい
> ケースは存在しますので、できればバックポートしていただきたいと思います。
> 
> 1.8への移行が困難な場合や、パッケージ・システムで1.8ベースのrubyがサポー
> トされるのに、まだ時間がかかりそうなOSもありますので...。

今から1.6系を各環境で確認するのが面倒というのが、あまりやりたく
ない理由です。やっぱりリリースされないとなかなか。

これで直るでしょうか。


Index: pty.c
===================================================================
RCS file: /cvs/ruby/src/ruby/ext/pty/pty.c,v
retrieving revision 1.5.2.5
diff -u -2 -p -r1.5.2.5 pty.c
--- ext/pty/pty.c	28 Jan 2002 08:42:38 -0000	1.5.2.5
+++ ext/pty/pty.c	12 Dec 2003 08:05:01 -0000
@@ -203,7 +203,19 @@ chld_changed()
 static void getDevice _((int*, int*));
 
+struct exec_info {
+    int argc;
+    VALUE *argv;
+};
+
+static VALUE
+pty_exec(arg)
+    struct exec_info *arg;
+{
+    return rb_funcall2(Qnil, rb_intern("exec"), arg->argc, arg->argv);
+}
+
 static void
-establishShell(shellname, info)
-    char *shellname;
+establishShell(command, info)
+    VALUE command;
     struct pty_info *info;
 {	
@@ -211,7 +223,20 @@ establishShell(shellname, info)
     char		*p,*getenv();
     struct passwd	*pwent;
-    RETSIGTYPE		chld_changed();
-    
-    if (shellname[0] == '\0') {
+    VALUE		v, *argv;
+    struct exec_info	arg;
+    int			status, argc;
+
+    if (TYPE(command) == T_ARRAY) {
+	argc = RARRAY(command)->len;
+	argv = RARRAY(command)->ptr;
+    }
+    else {
+	Check_SafeStr(command);
+	argc = RSTRING(command)->len ? 1 : 0;
+	argv = &command;
+    }
+    if (argc == 0) {
+	char *shellname;
+
 	if ((p = getenv("SHELL")) != NULL) {
 	    shellname = p;
@@ -224,4 +249,7 @@ establishShell(shellname, info)
 		shellname = "/bin/sh";
 	}
+	v = rb_str_new2(shellname);
+	argc = 1;
+	argv = &v;
     }
     getDevice(&master,&slave);
@@ -229,11 +257,11 @@ establishShell(shellname, info)
     currentPid = getpid();
     set_signal_action(chld_changed);
-    if((i = vfork()) < 0) {
+    if((i = fork()) < 0) {
+	close(master);
+	close(slave);
 	rb_sys_fail("fork failed");
     }
 
     if(i == 0) {	/* child */
-	int argc;
-	char *argv[1024];
 	currentPid = getpid();	
 
@@ -282,21 +310,11 @@ establishShell(shellname, info)
 	dup2(slave,2);
 	close(slave);
-
 #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
 	seteuid(getuid());
 #endif
 
-	argc = 0;
-	for (i = 0; shellname[i];) {
-	    while (isspace(shellname[i])) i++;
-	    for (j = i; shellname[j] && !isspace(shellname[j]); j++);
-	    argv[argc] = (char*)xmalloc(j-i+1);
-	    strncpy(argv[argc],&shellname[i],j-i);
-	    argv[argc][j-i] = 0;
-	    i = j;
-	    argc++;
-	}
-	argv[argc] = NULL;
-	execvp(argv[0],argv);
+	arg.argc = argc;
+	arg.argv = argv;
+	rb_protect(pty_exec, (VALUE)&arg, &status);
 	sleep(1);
 	_exit(1);
@@ -443,9 +461,5 @@ pty_getpty(self, command)
     MakeOpenFile(wport, wfptr);
 
-    if (TYPE(command) == T_ARRAY)
-	command = rb_ary_join(command,rb_str_new2(" "));
-    Check_SafeStr(command);
-
-    establishShell(RSTRING(command)->ptr,&info);
+    establishShell(command, &info);
 
     rfptr->mode = rb_io_mode_flags("r");


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread

Prev Next