ruby-changes:6306
From: suke <ko1@a...>
Date: Thu, 3 Jul 2008 00:35:19 +0900 (JST)
Subject: [ruby-changes:6306] Ruby:r17821 (trunk): * ext/win32ole/win32ole.c: avoid creating Ruby object during
suke 2008-07-03 00:35:04 +0900 (Thu, 03 Jul 2008)
New Revision: 17821
Modified files:
trunk/ChangeLog
trunk/ext/win32ole/win32ole.c
trunk/test/win32ole/test_win32ole_event.rb
Log:
* ext/win32ole/win32ole.c: avoid creating Ruby object during
GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313]
* test/win32ole/test_win32ole_event.rb: ditto.
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17821
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/test/win32ole/test_win32ole_event.rb?r1=17821&r2=17820&diff_format=u
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17821&r2=17820&diff_format=u
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ext/win32ole/win32ole.c?r1=17821&r2=17820&diff_format=u
Index: ChangeLog
===================================================================
--- ChangeLog (revision 17820)
+++ ChangeLog (revision 17821)
@@ -1,3 +1,10 @@
+Thu Jul 3 00:18:00 2008 Masaki Suketa <masaki.suketa@n...>
+
+ * ext/win32ole/win32ole.c: avoid creating Ruby object during
+ GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313]
+
+ * test/win32ole/test_win32ole_event.rb: ditto.
+
Thu Jul 3 00:09:31 2008 Masaki Suketa <masaki.suketa@n...>
* gc.c: add rb_during_gc(). based on a patch from arton <artonx AT
Index: ext/win32ole/win32ole.c
===================================================================
--- ext/win32ole/win32ole.c (revision 17820)
+++ ext/win32ole/win32ole.c (revision 17821)
@@ -31,6 +31,7 @@
#include <varargs.h>
#define va_init_list(a,b) va_start(a)
#endif
+#include <objidl.h>
#define DOUT fprintf(stderr,"[%d]\n",__LINE__)
#define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x)
@@ -116,7 +117,7 @@
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "1.1.7"
+#define WIN32OLE_VERSION "1.1.8"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -202,6 +203,9 @@
static char g_lcid_to_check[8 + 1];
static VARTYPE g_nil_to = VT_ERROR;
static st_table *enc2cp_table;
+static IMessageFilterVtbl message_filter;
+static IMessageFilter imessage_filter = { &message_filter };
+static IMessageFilter* previous_filter;
struct oledata {
IDispatch *pDispatch;
@@ -523,6 +527,101 @@
static void init_enc2cp();
static void free_enc2cp();
+static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
+{
+ if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
+ || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
+ {
+ *ppvObject = &message_filter;
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+static ULONG (STDMETHODCALLTYPE mf_AddRef)(
+ IMessageFilter __RPC_FAR * This)
+{
+ return 1;
+}
+
+static ULONG (STDMETHODCALLTYPE mf_Release)(
+ IMessageFilter __RPC_FAR * This)
+{
+ return 1;
+}
+
+static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
+ IMessageFilter __RPC_FAR * pThis,
+ DWORD dwCallType, //Type of incoming call
+ HTASK threadIDCaller, //Task handle calling this task
+ DWORD dwTickCount, //Elapsed tick count
+ LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
+ )
+{
+#ifdef DEBUG_MESSAGEFILTER
+ printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
+ fflush(stdout);
+#endif
+ switch (dwCallType)
+ {
+ case CALLTYPE_ASYNC:
+ case CALLTYPE_TOPLEVEL_CALLPENDING:
+ case CALLTYPE_ASYNC_CALLPENDING:
+ if (rb_during_gc()) {
+ return SERVERCALL_RETRYLATER;
+ }
+ break;
+ default:
+ break;
+ }
+ if (previous_filter) {
+ return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
+ dwCallType,
+ threadIDCaller,
+ dwTickCount,
+ lpInterfaceInfo);
+ }
+ return SERVERCALL_ISHANDLED;
+}
+
+static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
+ IMessageFilter* pThis,
+ HTASK threadIDCallee, //Server task handle
+ DWORD dwTickCount, //Elapsed tick count
+ DWORD dwRejectType //Returned rejection message
+ )
+{
+ if (previous_filter) {
+ return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
+ threadIDCallee,
+ dwTickCount,
+ dwRejectType);
+ }
+ return 1000;
+}
+
+static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
+ IMessageFilter* pThis,
+ HTASK threadIDCallee, //Called applications task handle
+ DWORD dwTickCount, //Elapsed tick count
+ DWORD dwPendingType //Call type
+ )
+{
+ if (rb_during_gc()) {
+ return PENDINGMSG_WAITNOPROCESS;
+ }
+ if (previous_filter) {
+ return previous_filter->lpVtbl->MessagePending(previous_filter,
+ threadIDCallee,
+ dwTickCount,
+ dwPendingType);
+ }
+ return PENDINGMSG_WAITNOPROCESS;
+}
+
typedef struct _Win32OLEIDispatch
{
IDispatch dispatch;
@@ -1059,6 +1158,11 @@
/*
atexit((void (*)(void))ole_uninitialize);
*/
+ hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
+ if(FAILED(hr)) {
+ previous_filter = NULL;
+ ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
+ }
}
}
@@ -8168,7 +8272,16 @@
com_vtbl.GetTypeInfo = GetTypeInfo;
com_vtbl.GetIDsOfNames = GetIDsOfNames;
com_vtbl.Invoke = Invoke;
+
+ message_filter.QueryInterface = mf_QueryInterface;
+ message_filter.AddRef = mf_AddRef;
+ message_filter.Release = mf_Release;
+ message_filter.HandleInComingCall = mf_HandleInComingCall;
+ message_filter.RetryRejectedCall = mf_RetryRejectedCall;
+ message_filter.MessagePending = mf_MessagePending;
+
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
+ com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
rb_register_mark_object(com_hash);
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
Index: test/win32ole/test_win32ole_event.rb
===================================================================
--- test/win32ole/test_win32ole_event.rb (revision 17820)
+++ test/win32ole/test_win32ole_event.rb (revision 17821)
@@ -35,6 +35,8 @@
ev.on_event {|*args| default_handler(*args)}
@ie.navigate("file:///#{@f}")
while @ie.busy
+ WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
+ GC.start
sleep 0.1
end
assert_match(/BeforeNavigate/, @event)
--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/