* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17821 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
suke 2008-07-02 15:35:04 +00:00
Родитель d2926df775
Коммит b892e3dd1b
3 изменённых файлов: 123 добавлений и 1 удалений

Просмотреть файл

@ -1,3 +1,10 @@
Thu Jul 3 00:18:00 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
* 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@nifty.ne.jp>
* gc.c: add rb_during_gc(). based on a patch from arton <artonx AT

Просмотреть файл

@ -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 UINT g_cp_to_check = CP_ACP;
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 VALUE folevariant_set_value(VALUE self, VALUE val);
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 @@ ole_initialize()
/*
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,6 +8272,15 @@ Init_win32ole()
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);

Просмотреть файл

@ -35,6 +35,8 @@ if defined?(WIN32OLE_EVENT)
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)