Skip to content

Commit eda0a8e

Browse files
author
wyhaines
committed
Backport ruby#1743 [ruby-core:24203]; stops timer thread unless other threads exist.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@26561 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent fdbf2bb commit eda0a8e

File tree

3 files changed

+81
-36
lines changed

3 files changed

+81
-36
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Wed Feb 4 01:06:00 2010 Kirk Haines <khaines@ruby-lang.org>
2+
3+
* eval.c: Backport #1743 [ruby-core:24203]; stops timer thread unless other threads exist.
4+
15
Wed Jan 28 04:00:00 2010 Kirk Haines <khaines@ruby-lang.org>
26

37
* io.c: Backport #2009 [ruby-core:25173]; (rb_io_fptr_finalize): free fptr to avoid memory leaks.

eval.c

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10569,6 +10569,12 @@ rb_thread_remove(th)
1056910569
rb_thread_die(th);
1057010570
th->prev->next = th->next;
1057110571
th->next->prev = th->prev;
10572+
#if defined(_THREAD_SAFE) || defined(HAVE_SETITIMER)
10573+
/* if this is the last ruby thread, stop timer signals */
10574+
if (th->next == th->prev && th->next == main_thread) {
10575+
rb_thread_stop_timer();
10576+
}
10577+
#endif
1057210578
}
1057310579

1057410580
static int
@@ -11955,58 +11961,98 @@ catch_timer(sig)
1195511961
/* cause EINTR */
1195611962
}
1195711963

11958-
static int time_thread_alive_p = 0;
11959-
static pthread_t time_thread;
11964+
#define PER_NANO 1000000000
11965+
11966+
static struct timespec *
11967+
get_ts(struct timespec *to, long ns)
11968+
{
11969+
struct timeval tv;
11970+
11971+
#ifdef CLOCK_MONOTONIC
11972+
if (clock_gettime(CLOCK_MONOTONIC, to) != 0)
11973+
#endif
11974+
{
11975+
gettimeofday(&tv, NULL);
11976+
to->tv_sec = tv.tv_sec;
11977+
to->tv_nsec = tv.tv_usec * 1000;
11978+
}
11979+
if ((to->tv_nsec += ns) >= PER_NANO) {
11980+
to->tv_sec += to->tv_nsec / PER_NANO;
11981+
to->tv_nsec %= PER_NANO;
11982+
}
11983+
return to;
11984+
}
11985+
11986+
static struct timer_thread {
11987+
pthread_cond_t cond;
11988+
pthread_mutex_t lock;
11989+
pthread_t thread;
11990+
} time_thread = {PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER};
11991+
11992+
#define safe_mutex_lock(lock) \
11993+
(pthread_mutex_lock(lock), \
11994+
pthread_cleanup_push((void (*)_((void *)))pthread_mutex_unlock, lock))
1196011995

1196111996
static void*
1196211997
thread_timer(dummy)
1196311998
void *dummy;
1196411999
{
11965-
#ifdef _THREAD_SAFE
11966-
#define test_cancel() pthread_testcancel()
11967-
#else
11968-
#define test_cancel() /* void */
11969-
#endif
12000+
struct timer_thread *running = ((void **)dummy)[0];
12001+
pthread_cond_t *start = ((void **)dummy)[1];
12002+
struct timespec to;
12003+
int err;
1197012004

1197112005
sigset_t all_signals;
1197212006

1197312007
sigfillset(&all_signals);
1197412008
pthread_sigmask(SIG_BLOCK, &all_signals, 0);
1197512009

11976-
for (;;) {
11977-
#ifdef HAVE_NANOSLEEP
11978-
struct timespec req, rem;
12010+
safe_mutex_lock(&running->lock);
12011+
pthread_cond_signal(start);
1197912012

11980-
test_cancel();
11981-
req.tv_sec = 0;
11982-
req.tv_nsec = 10000000;
11983-
nanosleep(&req, &rem);
11984-
#else
11985-
struct timeval tv;
11986-
11987-
test_cancel();
11988-
tv.tv_sec = 0;
11989-
tv.tv_usec = 10000;
11990-
select(0, NULL, NULL, NULL, &tv);
11991-
#endif
12013+
#define WAIT_FOR_10MS() \
12014+
pthread_cond_timedwait(&running->cond, &running->lock, get_ts(&to, PER_NANO/100))
12015+
while ((err = WAIT_FOR_10MS()) == EINTR || err == ETIMEDOUT) {
1199212016
if (!rb_thread_critical) {
1199312017
rb_thread_pending = 1;
1199412018
if (rb_trap_immediate) {
1199512019
pthread_kill(ruby_thid, SIGVTALRM);
1199612020
}
1199712021
}
1199812022
}
11999-
#undef test_cancel
12023+
12024+
pthread_cleanup_pop(1);
12025+
12026+
return NULL;
1200012027
}
1200112028

1200212029
void
1200312030
rb_thread_start_timer()
1200412031
{
12032+
void *args[2];
12033+
static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
12034+
12035+
if (!thread_init) return;
12036+
args[0] = &time_thread;
12037+
args[1] = &start;
12038+
safe_mutex_lock(&time_thread.lock);
12039+
if (pthread_create(&time_thread.thread, 0, thread_timer, args) == 0) {
12040+
thread_init = 1;
12041+
pthread_atfork(0, 0, rb_thread_stop_timer);
12042+
pthread_cond_wait(&start, &time_thread.lock);
12043+
}
12044+
pthread_cleanup_pop(1);
1200512045
}
1200612046

1200712047
void
1200812048
rb_thread_stop_timer()
1200912049
{
12050+
if (!thread_init) return;
12051+
safe_mutex_lock(&time_thread.lock);
12052+
pthread_cond_signal(&time_thread.cond);
12053+
pthread_cleanup_pop(1);
12054+
pthread_join(time_thread.thread, NULL);
12055+
thread_init = 0;
1201012056
}
1201112057

1201212058
void
@@ -12047,11 +12093,12 @@ rb_thread_start_timer()
1204712093
{
1204812094
struct itimerval tval;
1204912095

12050-
if (!thread_init) return;
12096+
if (thread_init) return;
1205112097
tval.it_interval.tv_sec = 0;
1205212098
tval.it_interval.tv_usec = 10000;
1205312099
tval.it_value = tval.it_interval;
1205412100
setitimer(ITIMER_VIRTUAL, &tval, NULL);
12101+
thread_init = 1;
1205512102
}
1205612103

1205712104
void
@@ -12064,6 +12111,7 @@ rb_thread_stop_timer()
1206412111
tval.it_interval.tv_usec = 0;
1206512112
tval.it_value = tval.it_interval;
1206612113
setitimer(ITIMER_VIRTUAL, &tval, NULL);
12114+
thread_init = 0;
1206712115
}
1206812116

1206912117
void
@@ -12098,21 +12146,14 @@ rb_thread_start_0(fn, arg, th)
1209812146
}
1209912147

1210012148
if (!thread_init) {
12101-
thread_init = 1;
1210212149
#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
1210312150
#if defined(POSIX_SIGNAL)
1210412151
posix_signal(SIGVTALRM, catch_timer);
1210512152
#else
1210612153
signal(SIGVTALRM, catch_timer);
1210712154
#endif
1210812155

12109-
#ifdef _THREAD_SAFE
12110-
pthread_create(&time_thread, 0, thread_timer, 0);
12111-
time_thread_alive_p = 1;
12112-
pthread_atfork(0, 0, rb_child_atfork);
12113-
#else
1211412156
rb_thread_start_timer();
12115-
#endif
1211612157
#endif
1211712158
}
1211812159

version.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#define RUBY_VERSION "1.8.6"
2-
#define RUBY_RELEASE_DATE "2010-01-28"
2+
#define RUBY_RELEASE_DATE "2010-02-04"
33
#define RUBY_VERSION_CODE 186
4-
#define RUBY_RELEASE_CODE 20100128
5-
#define RUBY_PATCHLEVEL 388
4+
#define RUBY_RELEASE_CODE 20100204
5+
#define RUBY_PATCHLEVEL 398
66

77
#define RUBY_VERSION_MAJOR 1
88
#define RUBY_VERSION_MINOR 8
99
#define RUBY_VERSION_TEENY 6
1010
#define RUBY_RELEASE_YEAR 2010
11-
#define RUBY_RELEASE_MONTH 1
12-
#define RUBY_RELEASE_DAY 28
11+
#define RUBY_RELEASE_MONTH 2
12+
#define RUBY_RELEASE_DAY 04
1313

1414
#ifdef RUBY_EXTERN
1515
RUBY_EXTERN const char ruby_version[];

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy