From: matz@... (Yukihiro Matsumoto) Date: 2001-11-16T14:20:26+09:00 Subject: [ruby-dev:15192] Re: strange behavior about PTY.spawn まつもと ゆきひろです In message "[ruby-dev:15185] Re: strange behavior about PTY.spawn" on 01/11/16, akira yamada / やまだあきら writes: |In article 15176, <1005839997.280842.1714.nullmailer@ev.netlab.jp> |Y> 1.7ではthread safeにしようとしてますが、 |Y> どうも不完全な気がします。 | |というのはどういう点ですか? main threadに例外を送ってる点とか。 |というのは当り前でSIGSTOPが来るとloop{}において例外が発生するのですよね(^_^; |で, たとえばですがこういう感じにするというのはどうでしょうか? 手元ではこういう風にしてます。確信がないのでコミットできませ んけど。 --- ext/pty/pty.c 2001/11/13 08:14:21 1.9 +++ ext/pty/pty.c 2001/11/16 05:16:02 @@ -109,4 +109,5 @@ struct pty_info { - int fd; - pid_t child_pid; + int fd; + pid_t child_pid; + VALUE thread; }; @@ -114,3 +115,4 @@ static void -pty_raise(cpid) +pty_raise(thread, cpid) + VALUE thread; int cpid; @@ -119,6 +121,4 @@ - snprintf(buf, sizeof(buf), - "eval %%Q{Thread.main.raise 'pty - stopped: %d'}, nil, \"%s\", %d", - cpid, ruby_sourcefile, ruby_sourceline); - rb_eval_string(buf); + snprintf(buf, sizeof(buf), "pty - stopped: %d", cpid); + rb_funcall(thread, rb_intern("raise"), 1, rb_str_new2(buf)); } @@ -126,10 +126,10 @@ static VALUE -pty_syswait(pid) - int pid; +pty_syswait(info) + struct pty_info *info; { int cpid, status; - - cpid = rb_waitpid(pid, &status, WUNTRACED); - printf("PTY command (%d) finished (%d:%d)\n", pid, cpid, status); + cpid = rb_waitpid(info->child_pid, &status, WUNTRACED); + printf("cpid: %d (%d)\n", cpid, status); + if (cpid == 0 || cpid == -1) @@ -139,3 +139,3 @@ if (IF_STOPPED(status)) { /* suspend */ - pty_raise(cpid); + pty_raise(info->thread, cpid); } @@ -144,3 +144,3 @@ if (WIFSTOPPED(status)) { /* suspend */ - pty_raise(cpid); + pty_raise(info->thread, cpid); } @@ -157,4 +157,5 @@ static void -establishShell(shellname, info) - char *shellname; +establishShell(argc, argv, info) + int argc; + VALUE *argv; struct pty_info *info; @@ -165,4 +166,7 @@ RETSIGTYPE chld_changed(); - - if (shellname[0] == '\0') { + VALUE v; + + if (argc == 0) { + char *shellname; + if ((p = getenv("SHELL")) != NULL) { @@ -177,2 +181,5 @@ } + v = rb_str_new2(shellname); + argc = 1; + argv = &v; } @@ -181,3 +188,3 @@ currentPid = getpid(); - if((i = vfork()) < 0) { + if((i = fork()) < 0) { rb_sys_fail("fork failed"); @@ -186,4 +193,4 @@ if(i == 0) { /* child */ - int argc; - char *argv[1024]; + /* int argc; + char *argv[1024]; */ currentPid = getpid(); @@ -234,3 +241,2 @@ close(slave); - #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) @@ -239,14 +245,3 @@ - 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); + rb_f_exec(argc, argv); sleep(1); @@ -363,4 +358,6 @@ static VALUE -pty_getpty(self, command) - VALUE self, command; +pty_getpty(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; { @@ -374,8 +371,4 @@ 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(argc, argv, &info); @@ -383,3 +376,3 @@ rfptr->f = fdopen(info.fd, "r"); - rfptr->path = strdup(RSTRING(command)->ptr); + rfptr->path = 0; /*strdup(RSTRING(command)->ptr); */ @@ -387,3 +380,3 @@ wfptr->f = fdopen(dup(info.fd), "w"); - wfptr->path = strdup(RSTRING(command)->ptr); + wfptr->path = 0; /* strdup(RSTRING(command)->ptr); */ @@ -394,4 +387,5 @@ - printf("start watching PTY command (%d)\n", info.child_pid); - th = rb_thread_create(pty_syswait, (void*)info.child_pid); + info.thread = rb_thread_current(); + printf("thread %p\n", info.thread); + th = rb_thread_create(pty_syswait, (void*)&info); if (rb_block_given_p()) { @@ -431,4 +425,4 @@ cPTY = rb_define_module("PTY"); - rb_define_module_function(cPTY,"getpty",pty_getpty,1); - rb_define_module_function(cPTY,"spawn",pty_getpty,1); + rb_define_module_function(cPTY,"getpty",pty_getpty,-1); + rb_define_module_function(cPTY,"spawn",pty_getpty,-1); rb_define_module_function(cPTY,"protect_signal",pty_protect,0);