1
0
Fork 0
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:
kosaki 2012-11-28 08:30:51 +00:00
parent fc57f2bfdb
commit b8a1e36201
5 changed files with 41 additions and 10 deletions

View file

@ -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> Wed Nov 28 16:59:12 2012 Koichi Sasada <ko1@atdot.net>
* proc.c: remove Proc#== and Proc#eql?. * proc.c: remove Proc#== and Proc#eql?.

View file

@ -278,6 +278,7 @@ VALUE rb_thread_shield_new(void);
VALUE rb_thread_shield_wait(VALUE self); VALUE rb_thread_shield_wait(VALUE self);
VALUE rb_thread_shield_release(VALUE self); VALUE rb_thread_shield_release(VALUE self);
VALUE rb_thread_shield_destroy(VALUE self); VALUE rb_thread_shield_destroy(VALUE self);
void rb_mutex_allow_trap(VALUE self, int val);
/* thread_pthread.c, thread_win32.c */ /* thread_pthread.c, thread_win32.c */
void Init_native_thread(void); void Init_native_thread(void);

1
io.c
View file

@ -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.capa = IO_WBUF_CAPA_MIN;
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa); fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
fptr->write_lock = rb_mutex_new(); fptr->write_lock = rb_mutex_new();
rb_mutex_allow_trap(fptr->write_lock, 1);
} }
if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) || if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
(fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) { (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {

View file

@ -260,4 +260,17 @@ EOS
end end
end 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 end

View file

@ -342,6 +342,7 @@ typedef struct rb_mutex_struct
struct rb_thread_struct volatile *th; struct rb_thread_struct volatile *th;
int cond_waiting; int cond_waiting;
struct rb_mutex_struct *next_mutex; struct rb_mutex_struct *next_mutex;
int allow_trap;
} rb_mutex_t; } rb_mutex_t;
static void rb_mutex_abandon_all(rb_mutex_t *mutexes); static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
@ -4140,16 +4141,15 @@ VALUE
rb_mutex_lock(VALUE self) rb_mutex_lock(VALUE self)
{ {
rb_thread_t *th = GET_THREAD(); rb_thread_t *th = GET_THREAD();
rb_mutex_t *mutex;
GetMutexPtr(self, mutex);
/* When running trap handler */ /* 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"); rb_raise(rb_eThreadError, "can't be called from trap context");
} }
if (rb_mutex_trylock(self) == Qfalse) { if (rb_mutex_trylock(self) == Qfalse) {
rb_mutex_t *mutex;
GetMutexPtr(self, mutex);
if (mutex->th == GET_THREAD()) { if (mutex->th == GET_THREAD()) {
rb_raise(rb_eThreadError, "deadlock; recursive locking"); rb_raise(rb_eThreadError, "deadlock; recursive locking");
} }
@ -4254,7 +4254,7 @@ rb_mutex_unlock(VALUE self)
GetMutexPtr(self, mutex); GetMutexPtr(self, mutex);
/* When running trap handler */ /* 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"); 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; 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); rb_scan_args(argc, argv, "01", &timeout);
return rb_mutex_sleep(self, 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); 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 * Document-class: ThreadShield
*/ */