From: "Nobuyoshi.Nakada" Date: 2000-08-31T00:33:26+09:00 Subject: [ruby-dev:10756] Re: ruby-1.6.0-20000824.i586-mswin32 bug なかだです。 At Wed, 30 Aug 2000 21:24:36 +0900 arton wrote: > 書き忘れてました。GetCurrentThread()で取れるのは、疑似ハンドルで実体では > ないため、次のように取ります。 > (なんで、そんな仕組みにしているのかは知りませんが、多分、本当のハンドル > を取るにはカーネルをロックして...みたいなオーバーヘッドがあるからでしょ > う。疑似ハンドルは、定数みたいです) だったら CURRENT_THREAD とかってマクロかなにかでも十分なんではって気も しますが。 > HANDLE hThread; > DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), > GetCurrentProcess(), > &hThread, 0, FALSE, DUPLICATE_SAME_ACCESS); > > このDupしたハンドルが、本当のハンドルになります。(この処理は、当然、メ > インスレッド自身で呼び出す必要があります) Duplicate なので毎回違った値を返すようです。比較の方法が分からなかった ので、GetCurrentThreadId() を使ってみました。 かなり強引というか、処理系に依存することをしてます。これって mingw32 でも一応通るようですが、どうなんでしょう。そもそも mingw32 だとこんなこ と要らない? そういえば cygwin だとどうなってるんでしょうか。 diff -pruPX ./.excludes current/signal.c devel/signal.c --- current/signal.c Mon Aug 7 14:01:57 2000 +++ devel/signal.c Thu Aug 31 00:00:48 2000 @@ -341,6 +341,11 @@ static RETSIGTYPE sighandle(sig) int sig; { +#ifdef NT + extern int win32_main_context(int arg, void handler(int)); + if (win32_main_context(sig, sighandle)) return; +#endif + if (sig >= NSIG) { rb_bug("trap_handler: Bad signal %d", sig); } diff -pruPX ./.excludes current/win32/win32.c devel/win32/win32.c --- current/win32/win32.c Tue Aug 15 16:11:13 2000 +++ devel/win32/win32.c Thu Aug 31 00:06:29 2000 @@ -75,6 +75,9 @@ IsWinNT(void) { return (IdOS() == VER_PLATFORM_WIN32_NT); } +/* main thread constants */ +HANDLE rb_MainThreadHandle; +DWORD rb_MainThreadId; /* simulate flock by locking a range on the file */ @@ -164,6 +167,11 @@ NtInitialize(int *argc, char ***argv) { WORD version; int ret; + HANDLE proc = GetCurrentProcess(); + + DuplicateHandle(proc, GetCurrentThread(), proc, + &rb_MainThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); + rb_MainThreadId = GetCurrentThreadId(); // // subvert cmd.exe\'s feeble attempt at command line parsing @@ -2498,4 +2506,36 @@ mytimes(struct tms *tmbuf) tmbuf->tms_cstime = 0; } return 0; +} + +static void __stdcall +win32_call_handler(int arg, void handler(int)) +{ + handler(arg); +} + +int +win32_main_context(int arg, void handler(int)) +{ + CONTEXT con; + + if (GetCurrentThreadId() == rb_MainThreadId) return FALSE; + + SuspendThread(rb_MainThreadHandle); + ZeroMemory(&con, sizeof(CONTEXT)); + con.ContextFlags = CONTEXT_CONTROL; + GetThreadContext(rb_MainThreadHandle, &con); + con.ContextFlags = CONTEXT_CONTROL; +#ifdef _M_IX86 + con.Esp -= 3 * sizeof(DWORD); + ((DWORD *)con.Esp)[2] = (DWORD)handler; + ((DWORD *)con.Esp)[1] = arg; + ((DWORD *)con.Esp)[0] = con.Eip; + con.Eip = (DWORD)win32_call_handler;; +#else +#error +#endif + SetThreadContext(rb_MainThreadHandle, &con); + ResumeThread(rb_MainThreadHandle); + return TRUE; } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦