From: "U.Nakamura" Date: 2001-06-01T03:23:26+09:00 Subject: [ruby-dev:13428] mswin32/ming32 system patch (experimental) こんにちは、なかむら(う)です。 以前、mswin32/mingw32でのsystemの挙動を改良しようと試みて パッチを投げたことがありましたが、つい先日Patrick Chenz氏 から似たような発想(spawnvpe()の替わりにCreateProcess()を 直接叩く)のパッチを頂きましたので、それをベースにして再度 試験的なパッチを作成してみました。 改良したつもりの点は以下の通り。 1.現在のCVS HEADの実装だと、 system("\"d:\\bin\\test\\test.bat\" \"this is a test\" 1") system("\"d:/bin/test/test.bat\" \"this is a test\" 1") が正しく動作しないが、今回の実装だと動作する。 (Chenz氏による改良) 2.現在のCVS HEADの実装だとsystemを叩くとそのコマンドが 終了するまで全スレッドが停止するが、今回の実装だと他 のスレッドは動きつづける。 (私による改良) なお、まだ手抜きの部分があるので、コードが整理されてなか ったりしますが、それは気にしないで下さい :-P ただ、このやり方がいいかどうかは僕自身にも自信はなくて、 [ruby-dev:12121]でなかださんがおっしゃっているように spawnvpe()のままでrb_syswait()(か、それがダメなら今回の ようにrb_waitpid()あたり)で待つようにするアプローチの方が 筋がいいかもしれません。 ご意見よろしくお願いします。 diff -p2ur current/process.c mytree/process.c --- current/process.c Tue May 22 23:34:12 2001 +++ mytree/process.c Fri Jun 1 02:33:44 2001 @@ -228,5 +228,5 @@ static st_table *pid_tbl; #endif -static int +int rb_waitpid(pid, flags, st) int pid; diff -p2ur current/win32/win32.c mytree/win32/win32.c --- current/win32/win32.c Sat May 12 15:43:28 2001 +++ mytree/win32/win32.c Fri Jun 1 02:56:44 2001 @@ -790,4 +790,5 @@ char *cmd; } +#if 0 argv = ALLOC_N(CHARP, (strlen(cmd) / 2 + 2)); cmd2 = ALLOC_N(char, (strlen(cmd) + 1)); @@ -839,5 +840,60 @@ char *cmd; free(cmd2); free(argv); + return (int)((status & 0xff) << 8); +#else + { + BOOL fRet; + LPCSTR lpApplicationName = NULL; + LPTSTR lpCommandLine; + LPTSTR lpCmd2 = NULL; + DWORD dwCreationFlags; + STARTUPINFO aStartupInfo; + PROCESS_INFORMATION aProcessInformation; + SECURITY_ATTRIBUTES sa; + int ret; + int rb_waitpid(int, int, int*); + + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + + memset(&aStartupInfo, 0, sizeof (STARTUPINFO)); + memset(&aProcessInformation, 0, sizeof (PROCESS_INFORMATION)); + aStartupInfo.cb = sizeof (STARTUPINFO); + + dwCreationFlags = (NORMAL_PRIORITY_CLASS); + + lpCommandLine = cmd; + /* + if (NtHasRedirection(cmd) || isInternalCmd(cmd)) { + lpApplicationName = getenv("COMSPEC"); + lpCmd2 = ALLOC_N(char, strlen(lpApplicationName) + 1 + strlen(cmd) + sizeof (" /c ")); + sprintf(lpCmd2, "%s %s%s", lpApplicationName, " /c ", cmd); + lpCommandLine = lpCmd2; + } + */ + RUBY_CRITICAL({ + fRet = CreateProcess(lpApplicationName, lpCommandLine, &sa, &sa, + sa.bInheritHandle, dwCreationFlags, NULL, NULL, + &aStartupInfo, &aProcessInformation); + }); + if (lpCmd2) + free(lpCmd2); + + if ( ! fRet ) { + errno = GetLastError(); + rb_sys_fail("do_spawn: CreateProcess"); + } + + do { + ret = rb_waitpid((int)aProcessInformation.hProcess, 0, &status); + } while (ret == -1 && errno == EINTR); + CloseHandle(aProcessInformation.hThread); + CloseHandle(aProcessInformation.hProcess); + } + + return status; +#endif //0 } それでは。 -- U.Nakamura