mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* thread.c (struct rb_mutex_struct): add allow_trap field.
* internal.h (rb_mutex_allow_trap): added. * thread.c (rb_mutex_lock, rb_mutex_unlock): check mutex->allow_trap. * thread.c (mutex_sleep): remove trap check because it uses rb_mutex_lock and rb_mutex_unlock internally. * thread.c (rb_mutex_allow_trap): new helper function for the above. * io.c (io_binwrite): mark fptr->write_lock as writable in trap. * test/ruby/test_signal.rb (test_trap_puts): test for the above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37930 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fc57f2bfdb
commit
b8a1e36201
5 changed files with 41 additions and 10 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
|||
Wed Nov 28 16:21:46 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||||
|
||||
* thread.c (struct rb_mutex_struct): add allow_trap field.
|
||||
* internal.h (rb_mutex_allow_trap): added.
|
||||
* thread.c (rb_mutex_lock, rb_mutex_unlock): check mutex->allow_trap.
|
||||
* thread.c (mutex_sleep): remove trap check because it uses
|
||||
rb_mutex_lock and rb_mutex_unlock internally.
|
||||
* thread.c (rb_mutex_allow_trap): new helper function for the above.
|
||||
|
||||
* io.c (io_binwrite): mark fptr->write_lock as writable in trap.
|
||||
|
||||
* test/ruby/test_signal.rb (test_trap_puts): test for the above.
|
||||
|
||||
Wed Nov 28 16:59:12 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* proc.c: remove Proc#== and Proc#eql?.
|
||||
|
|
|
@ -278,6 +278,7 @@ VALUE rb_thread_shield_new(void);
|
|||
VALUE rb_thread_shield_wait(VALUE self);
|
||||
VALUE rb_thread_shield_release(VALUE self);
|
||||
VALUE rb_thread_shield_destroy(VALUE self);
|
||||
void rb_mutex_allow_trap(VALUE self, int val);
|
||||
|
||||
/* thread_pthread.c, thread_win32.c */
|
||||
void Init_native_thread(void);
|
||||
|
|
1
io.c
1
io.c
|
@ -1126,6 +1126,7 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
|
|||
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
|
||||
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
|
||||
fptr->write_lock = rb_mutex_new();
|
||||
rb_mutex_allow_trap(fptr->write_lock, 1);
|
||||
}
|
||||
if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
|
||||
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
|
||||
|
|
|
@ -260,4 +260,17 @@ EOS
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_trap_puts
|
||||
assert_in_out_err([], <<-INPUT, ["a"*10000], [])
|
||||
Signal.trap(:INT) {
|
||||
# for enable internal io mutex
|
||||
sync = false
|
||||
# larger than internal io buffer
|
||||
print "a"*10000
|
||||
}
|
||||
Process.kill :INT, $$
|
||||
sleep 0.1
|
||||
INPUT
|
||||
end
|
||||
end
|
||||
|
|
23
thread.c
23
thread.c
|
@ -342,6 +342,7 @@ typedef struct rb_mutex_struct
|
|||
struct rb_thread_struct volatile *th;
|
||||
int cond_waiting;
|
||||
struct rb_mutex_struct *next_mutex;
|
||||
int allow_trap;
|
||||
} rb_mutex_t;
|
||||
|
||||
static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
|
||||
|
@ -4140,16 +4141,15 @@ VALUE
|
|||
rb_mutex_lock(VALUE self)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_mutex_t *mutex;
|
||||
GetMutexPtr(self, mutex);
|
||||
|
||||
/* When running trap handler */
|
||||
if (th->interrupt_mask & TRAP_INTERRUPT_MASK) {
|
||||
if (!mutex->allow_trap && th->interrupt_mask & TRAP_INTERRUPT_MASK) {
|
||||
rb_raise(rb_eThreadError, "can't be called from trap context");
|
||||
}
|
||||
|
||||
if (rb_mutex_trylock(self) == Qfalse) {
|
||||
rb_mutex_t *mutex;
|
||||
GetMutexPtr(self, mutex);
|
||||
|
||||
if (mutex->th == GET_THREAD()) {
|
||||
rb_raise(rb_eThreadError, "deadlock; recursive locking");
|
||||
}
|
||||
|
@ -4254,7 +4254,7 @@ rb_mutex_unlock(VALUE self)
|
|||
GetMutexPtr(self, mutex);
|
||||
|
||||
/* When running trap handler */
|
||||
if (GET_THREAD()->interrupt_mask & TRAP_INTERRUPT_MASK) {
|
||||
if (!mutex->allow_trap && GET_THREAD()->interrupt_mask & TRAP_INTERRUPT_MASK) {
|
||||
rb_raise(rb_eThreadError, "can't be called from trap context");
|
||||
}
|
||||
|
||||
|
@ -4326,11 +4326,6 @@ mutex_sleep(int argc, VALUE *argv, VALUE self)
|
|||
{
|
||||
VALUE timeout;
|
||||
|
||||
/* When running trap handler */
|
||||
if (GET_THREAD()->interrupt_mask & TRAP_INTERRUPT_MASK) {
|
||||
rb_raise(rb_eThreadError, "can't be called from trap context");
|
||||
}
|
||||
|
||||
rb_scan_args(argc, argv, "01", &timeout);
|
||||
return rb_mutex_sleep(self, timeout);
|
||||
}
|
||||
|
@ -4367,6 +4362,14 @@ rb_mutex_synchronize_m(VALUE self, VALUE args)
|
|||
return rb_mutex_synchronize(self, rb_yield, Qnil);
|
||||
}
|
||||
|
||||
void rb_mutex_allow_trap(VALUE self, int val)
|
||||
{
|
||||
rb_mutex_t *m;
|
||||
GetMutexPtr(self, m);
|
||||
|
||||
m->allow_trap = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Document-class: ThreadShield
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue