aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--thread_win32.c48
-rw-r--r--thread_win32.h2
3 files changed, 48 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index 55f77aecef..38e9330e40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Sat May 7 15:15:10 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ fix win32 native_cond_timedwait() makes SIGSEGV.
+
+ * thread_win32.h (rb_thread_cond_struct): add prev field instead of last.
+ (ie cond_event_entry is now using double linked list instead of single)
+ * thread_win32.c (cond_event_entry): add prev field.
+
+ * thread_win32.c (__cond_timedwait): remove entry properly if timeout
+ was happen.
+
+ * thread_win32.c (native_cond_signal): change for double linked list.
+ * thread_win32.c (native_cond_broadcast): ditto.
+ * thread_win32.c (native_cond_initialize): ditto.
+
Sat May 7 12:41:04 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
fix mutex deadlock test hang-up.
diff --git a/thread_win32.c b/thread_win32.c
index 6c7e0d2669..360013db43 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -393,6 +393,7 @@ native_mutex_destroy(rb_thread_lock_t *lock)
struct cond_event_entry {
struct cond_event_entry* next;
+ struct cond_event_entry* prev;
HANDLE event;
};
@@ -401,9 +402,16 @@ native_cond_signal(rb_thread_cond_t *cond)
{
/* cond is guarded by mutex */
struct cond_event_entry *e = cond->next;
+ struct cond_event_entry *head = (struct cond_event_entry*)cond;
+
+ if (e != head) {
+ struct cond_event_entry *next = e->next;
+ struct cond_event_entry *prev = e->prev;
+
+ prev->next = next;
+ next->prev = prev;
+ e->next = e->prev = e;
- if (e) {
- cond->next = e->next;
SetEvent(e->event);
}
else {
@@ -416,11 +424,19 @@ native_cond_broadcast(rb_thread_cond_t *cond)
{
/* cond is guarded by mutex */
struct cond_event_entry *e = cond->next;
- cond->next = 0;
+ struct cond_event_entry *head = (struct cond_event_entry*)cond;
+
+ while (e != head) {
+ struct cond_event_entry *next = e->next;
+ struct cond_event_entry *prev = e->prev;
- while (e) {
SetEvent(e->event);
- e = e->next;
+
+ prev->next = next;
+ next->prev = prev;
+ e->next = e->prev = e;
+
+ e = next;
}
}
@@ -430,19 +446,16 @@ __cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, unsigned long
{
DWORD r;
struct cond_event_entry entry;
+ struct cond_event_entry *head = (struct cond_event_entry*)cond;
- entry.next = 0;
entry.event = CreateEvent(0, FALSE, FALSE, 0);
+ entry.mutex = mutex;
/* cond is guarded by mutex */
- if (cond->next) {
- cond->last->next = &entry;
- cond->last = &entry;
- }
- else {
- cond->next = &entry;
- cond->last = &entry;
- }
+ entry.next = head;
+ entry.prev = head->prev;
+ head->prev->next = &entry;
+ head->prev = &entry;
native_mutex_unlock(mutex);
{
@@ -453,6 +466,9 @@ __cond_timedwait(rb_thread_cond_t *cond, rb_thread_lock_t *mutex, unsigned long
}
native_mutex_lock(mutex);
+ entry.prev->next = entry.next;
+ entry.next->prev = entry.prev;
+
w32_close_handle(entry.event);
return (r == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
}
@@ -537,8 +553,8 @@ native_cond_timeout(rb_thread_cond_t *cond, struct timespec timeout_rel)
static void
native_cond_initialize(rb_thread_cond_t *cond, int flags)
{
- cond->next = 0;
- cond->last = 0;
+ cond->next = (struct cond_event_entry *)cond;
+ cond->prev = (struct cond_event_entry *)cond;
}
static void
diff --git a/thread_win32.h b/thread_win32.h
index b7ab91ea44..4098a42606 100644
--- a/thread_win32.h
+++ b/thread_win32.h
@@ -25,7 +25,7 @@ typedef HANDLE rb_thread_id_t;
typedef CRITICAL_SECTION rb_thread_lock_t;
typedef struct rb_thread_cond_struct {
struct cond_event_entry *next;
- struct cond_event_entry *last;
+ struct cond_event_entry *prev;
} rb_thread_cond_t;
typedef struct native_thread_data_struct {