evio 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/evio/ev.c +108 -0
- data/ext/evio/evio.c +14 -0
- data/ext/evio/evio.h +33 -0
- data/ext/evio/extconf.rb +29 -0
- data/ext/evio/io.c +170 -0
- data/ext/evio/signal.c +308 -0
- data/lib/evio.rb +2 -0
- data/lib/evio/signal.rb +18 -0
- metadata +69 -0
data/ext/evio/ev.c
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ev.h>
|
3
|
+
|
4
|
+
#include "evio.h"
|
5
|
+
|
6
|
+
|
7
|
+
static void
|
8
|
+
prepare_cb(struct ev_loop *loop, ev_prepare *watcher, int revents)
|
9
|
+
{
|
10
|
+
prepare_data *data = watcher->data;
|
11
|
+
|
12
|
+
rb_funcall(data->block, rb_intern("call"), 0);
|
13
|
+
ev_prepare_stop(loop, watcher);
|
14
|
+
rb_gc_unregister_address(&data->block);
|
15
|
+
free(data);
|
16
|
+
free(watcher);
|
17
|
+
}
|
18
|
+
|
19
|
+
static void
|
20
|
+
timer_cb(struct ev_loop *loop, ev_timer *watcher, int revents)
|
21
|
+
{
|
22
|
+
timer_data *data = watcher->data;
|
23
|
+
VALUE rv;
|
24
|
+
|
25
|
+
rv = rb_funcall(data->block, rb_intern("call"), 0);
|
26
|
+
|
27
|
+
if (data->repeat == 0 || rv == Qfalse) {
|
28
|
+
// remove watcher from loop
|
29
|
+
ev_timer_stop(loop, watcher);
|
30
|
+
// make the block available for gc collect
|
31
|
+
rb_gc_unregister_address(&data->block);
|
32
|
+
// free resources unmanaged by the gc
|
33
|
+
free(data);
|
34
|
+
free(watcher);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
static VALUE
|
39
|
+
set_timer(VALUE self, VALUE delay, VALUE repeat_delay)
|
40
|
+
{
|
41
|
+
ev_timer *watcher;
|
42
|
+
timer_data *data;
|
43
|
+
int type;
|
44
|
+
double dl, repeat_dl;
|
45
|
+
|
46
|
+
rb_secure(2);
|
47
|
+
|
48
|
+
if ((type = TYPE(delay)) == T_FLOAT || type == T_FIXNUM)
|
49
|
+
dl = NUM2DBL(delay);
|
50
|
+
else
|
51
|
+
rb_raise(rb_eArgError, "first argument must be a number");
|
52
|
+
|
53
|
+
if ((type = TYPE(repeat_delay)) == T_FLOAT || type == T_FIXNUM)
|
54
|
+
repeat_dl = NUM2DBL(repeat_delay);
|
55
|
+
else
|
56
|
+
rb_raise(rb_eArgError, "second argument must be a number");
|
57
|
+
|
58
|
+
if (!rb_block_given_p())
|
59
|
+
rb_raise(rb_eArgError, "a block is required");
|
60
|
+
|
61
|
+
watcher = ALLOC(ev_timer);
|
62
|
+
data = ALLOC(timer_data);
|
63
|
+
// bind the block to its outer scope and store for later use
|
64
|
+
data->block = rb_block_proc();
|
65
|
+
// don't let the gc collect it
|
66
|
+
rb_gc_register_address(&data->block);
|
67
|
+
watcher->data = data;
|
68
|
+
if (repeat_dl > 0) data->repeat = 1;
|
69
|
+
else data->repeat = 0;
|
70
|
+
ev_timer_init(watcher, timer_cb, dl, repeat_dl);
|
71
|
+
ev_timer_start(loop, watcher);
|
72
|
+
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE
|
77
|
+
start_loop(VALUE self)
|
78
|
+
{
|
79
|
+
ev_prepare *watcher;
|
80
|
+
prepare_data *data;
|
81
|
+
|
82
|
+
if (rb_block_given_p()) {
|
83
|
+
watcher = ALLOC(ev_prepare);
|
84
|
+
data = ALLOC(prepare_data);
|
85
|
+
data->block = rb_block_proc();
|
86
|
+
rb_gc_register_address(&data->block);
|
87
|
+
watcher->data = data;
|
88
|
+
ev_prepare_init(watcher, prepare_cb);
|
89
|
+
ev_prepare_start(loop, watcher);
|
90
|
+
}
|
91
|
+
|
92
|
+
ev_run(loop, 0);
|
93
|
+
return Qnil;
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE
|
97
|
+
stop_loop(VALUE self)
|
98
|
+
{
|
99
|
+
ev_break(loop, EVBREAK_ALL);
|
100
|
+
return Qnil;
|
101
|
+
}
|
102
|
+
|
103
|
+
void init_ev(VALUE module)
|
104
|
+
{
|
105
|
+
rb_define_module_function(module, "set_timer", set_timer, 2);
|
106
|
+
rb_define_module_function(module, "start_loop", start_loop, 0);
|
107
|
+
rb_define_module_function(module, "stop_loop", stop_loop, 0);
|
108
|
+
}
|
data/ext/evio/evio.c
ADDED
data/ext/evio/evio.h
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
typedef struct {
|
3
|
+
int fd;
|
4
|
+
int closed;
|
5
|
+
enum {
|
6
|
+
file,
|
7
|
+
socket
|
8
|
+
} stream_type;
|
9
|
+
|
10
|
+
} io_stream;
|
11
|
+
|
12
|
+
struct block_wrapper {
|
13
|
+
VALUE block;
|
14
|
+
};
|
15
|
+
|
16
|
+
typedef struct block_wrapper signal_data;
|
17
|
+
typedef struct block_wrapper prepare_data;
|
18
|
+
typedef struct {
|
19
|
+
VALUE block;
|
20
|
+
int buffer_size;
|
21
|
+
char *buffer;
|
22
|
+
} io_read_data;
|
23
|
+
typedef struct {
|
24
|
+
VALUE block;
|
25
|
+
int repeat;
|
26
|
+
} timer_data;
|
27
|
+
|
28
|
+
struct ev_loop *loop;
|
29
|
+
|
30
|
+
void Init_evio();
|
31
|
+
void init_ev(VALUE module);
|
32
|
+
void init_signal(VALUE module);
|
33
|
+
void init_io(VALUE module);
|
data/ext/evio/extconf.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
HEADER_DIRS = [
|
6
|
+
'/opt/local/include',
|
7
|
+
'/usr/local/include',
|
8
|
+
Config::CONFIG['includedir'],
|
9
|
+
'/usr/include',
|
10
|
+
]
|
11
|
+
|
12
|
+
LIB_DIRS = [
|
13
|
+
'/opt/local/lib',
|
14
|
+
'/usr/local/lib',
|
15
|
+
Config::CONFIG['libdir'],
|
16
|
+
'/usr/lib',
|
17
|
+
]
|
18
|
+
|
19
|
+
dir_config('ev', HEADER_DIRS, LIB_DIRS)
|
20
|
+
|
21
|
+
unless find_header('ev.h')
|
22
|
+
abort 'cannot find libev headers, install it before continuing'
|
23
|
+
end
|
24
|
+
|
25
|
+
unless find_library('ev', 'ev_run')
|
26
|
+
abort 'cannot find libev'
|
27
|
+
end
|
28
|
+
|
29
|
+
create_makefile('evio/evio')
|
data/ext/evio/io.c
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
#include <errno.h>
|
2
|
+
#include <string.h>
|
3
|
+
|
4
|
+
#include <sys/types.h>
|
5
|
+
#include <sys/stat.h>
|
6
|
+
#include <fcntl.h>
|
7
|
+
#include <unistd.h>
|
8
|
+
|
9
|
+
#include <ruby.h>
|
10
|
+
#include <ev.h>
|
11
|
+
|
12
|
+
#include "evio.h"
|
13
|
+
|
14
|
+
|
15
|
+
VALUE cIO;
|
16
|
+
|
17
|
+
static void
|
18
|
+
io_free(io_stream *stream)
|
19
|
+
{
|
20
|
+
close(stream->fd);
|
21
|
+
free(stream);
|
22
|
+
}
|
23
|
+
|
24
|
+
static VALUE
|
25
|
+
io_open(int argc, VALUE *argv)
|
26
|
+
{
|
27
|
+
io_stream *stream;
|
28
|
+
char *path, *mode;
|
29
|
+
int flags, filemode;
|
30
|
+
|
31
|
+
rb_secure(2);
|
32
|
+
|
33
|
+
if (argc < 1 || argc > 3)
|
34
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", argc);
|
35
|
+
|
36
|
+
if (TYPE(argv[0]) != T_STRING)
|
37
|
+
rb_raise(rb_eArgError, "first argument must be a string");
|
38
|
+
|
39
|
+
path = RSTRING_PTR(rb_str_encode_ospath(argv[0]));
|
40
|
+
|
41
|
+
if (argc > 1) {
|
42
|
+
flags = -1;
|
43
|
+
if (TYPE(argv[1]) != T_STRING)
|
44
|
+
rb_raise(rb_eArgError, "second argument must be a string");
|
45
|
+
mode = RSTRING_PTR(argv[1]);
|
46
|
+
if (mode[0] == 'r') {
|
47
|
+
if (mode[1] == '\0')
|
48
|
+
flags = O_RDONLY;
|
49
|
+
else if (mode[1] == '+' && mode[2] == '\0')
|
50
|
+
flags = O_RDWR;
|
51
|
+
} else if (mode[0] == 'w') {
|
52
|
+
if (mode[1] == '\0')
|
53
|
+
flags = O_WRONLY | O_CREAT;
|
54
|
+
else if (mode[1] == '+' && mode[2] == '\0')
|
55
|
+
flags = O_RDWR | O_CREAT;
|
56
|
+
} else if (mode[0] == 'a') {
|
57
|
+
if (mode[1] == '\0')
|
58
|
+
flags = O_WRONLY | O_CREAT | O_APPEND;
|
59
|
+
else if (mode[1] == '+' && mode[2] == '\0')
|
60
|
+
flags = O_RDWR | O_CREAT | O_APPEND;
|
61
|
+
}
|
62
|
+
if (flags == -1) rb_raise(rb_eArgError, "invalid file mode string");
|
63
|
+
} else {
|
64
|
+
flags = O_RDONLY;
|
65
|
+
}
|
66
|
+
|
67
|
+
if (argc == 3) {
|
68
|
+
if (TYPE(argv[2]) != T_FIXNUM)
|
69
|
+
rb_raise(rb_eArgError, "third argument must be an integer");
|
70
|
+
filemode = FIX2INT(argv[2]);
|
71
|
+
} else {
|
72
|
+
filemode = 0644;
|
73
|
+
}
|
74
|
+
|
75
|
+
flags |= O_NONBLOCK;
|
76
|
+
stream = ALLOC(io_stream);
|
77
|
+
stream->fd = open(path, flags, filemode);
|
78
|
+
|
79
|
+
if (stream->fd == -1)
|
80
|
+
rb_raise(rb_eSystemCallError, "%s", strerror(errno));
|
81
|
+
|
82
|
+
return Data_Wrap_Struct(cIO, 0, io_free, stream);
|
83
|
+
}
|
84
|
+
|
85
|
+
static void
|
86
|
+
io_read_cb(struct ev_loop *loop, ev_io *watcher, int revents)
|
87
|
+
{
|
88
|
+
ssize_t read_count;
|
89
|
+
VALUE rv = Qnil;
|
90
|
+
VALUE ex = Qnil;
|
91
|
+
io_read_data *data = watcher->data;
|
92
|
+
|
93
|
+
read_count = read(watcher->fd, data->buffer, data->buffer_size);
|
94
|
+
|
95
|
+
if (read_count == -1) {
|
96
|
+
if (errno == EAGAIN) return;
|
97
|
+
else ex = rb_exc_new2(rb_eSystemCallError, strerror(errno));
|
98
|
+
}
|
99
|
+
|
100
|
+
if (read_count != 0) // not EOF
|
101
|
+
rv = rb_funcall(data->block, rb_intern("call"), 2, ex,
|
102
|
+
rb_str_new(data->buffer, read_count));
|
103
|
+
|
104
|
+
if (read_count == 0 || rv == Qfalse) {
|
105
|
+
ev_io_stop(loop, watcher);
|
106
|
+
rb_gc_unregister_address(&data->block);
|
107
|
+
free(data->buffer);
|
108
|
+
free(data);
|
109
|
+
free(watcher);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE
|
114
|
+
io_read(int argc, VALUE *argv, VALUE self)
|
115
|
+
{
|
116
|
+
ev_io *watcher;
|
117
|
+
io_read_data *data;
|
118
|
+
io_stream *stream;
|
119
|
+
int buffer_size;
|
120
|
+
|
121
|
+
rb_secure(2);
|
122
|
+
|
123
|
+
if (argc > 1)
|
124
|
+
rb_raise(rb_eArgError, "must provide zero or one arguments");
|
125
|
+
|
126
|
+
if (!rb_block_given_p())
|
127
|
+
rb_raise(rb_eArgError, "a block is required");
|
128
|
+
|
129
|
+
if (argc == 1) {
|
130
|
+
if (TYPE(argv[0]) != T_FIXNUM)
|
131
|
+
rb_raise(rb_eArgError, "first argument must be an integer");
|
132
|
+
buffer_size = FIX2INT(argv[0]);
|
133
|
+
} else {
|
134
|
+
buffer_size = 4096;
|
135
|
+
}
|
136
|
+
|
137
|
+
Data_Get_Struct(self, io_stream, stream);
|
138
|
+
watcher = ALLOC(ev_io);
|
139
|
+
data = ALLOC(io_read_data);
|
140
|
+
data->block = rb_block_proc();
|
141
|
+
data->buffer_size = buffer_size;
|
142
|
+
data->buffer = ALLOC_N(char, buffer_size);
|
143
|
+
rb_gc_register_address(&data->block);
|
144
|
+
watcher->data = data;
|
145
|
+
ev_io_init(watcher, io_read_cb, stream->fd, EV_READ);
|
146
|
+
ev_io_start(loop, watcher);
|
147
|
+
|
148
|
+
return Qnil;
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE
|
152
|
+
io_close(VALUE self)
|
153
|
+
{
|
154
|
+
io_stream *stream;
|
155
|
+
|
156
|
+
Data_Get_Struct(self, io_stream, stream);
|
157
|
+
close(stream->fd);
|
158
|
+
|
159
|
+
return Qnil;
|
160
|
+
}
|
161
|
+
|
162
|
+
void init_io(VALUE module)
|
163
|
+
{
|
164
|
+
cIO = rb_define_class_under(module, "IO", rb_cObject);
|
165
|
+
|
166
|
+
rb_define_singleton_method(cIO, "open", io_open, -1);
|
167
|
+
|
168
|
+
rb_define_method(cIO, "read", io_read, -1);
|
169
|
+
rb_define_method(cIO, "close", io_close, 0);
|
170
|
+
}
|
data/ext/evio/signal.c
ADDED
@@ -0,0 +1,308 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ev.h>
|
3
|
+
|
4
|
+
#include "evio.h"
|
5
|
+
|
6
|
+
// mostly copied from signal.c(ruby source)
|
7
|
+
|
8
|
+
static const struct signals {
|
9
|
+
const char *signm;
|
10
|
+
int signo;
|
11
|
+
} siglist [] = {
|
12
|
+
{"EXIT", 0},
|
13
|
+
#ifdef SIGHUP
|
14
|
+
{"HUP", SIGHUP},
|
15
|
+
#endif
|
16
|
+
{"INT", SIGINT},
|
17
|
+
#ifdef SIGQUIT
|
18
|
+
{"QUIT", SIGQUIT},
|
19
|
+
#endif
|
20
|
+
#ifdef SIGILL
|
21
|
+
{"ILL", SIGILL},
|
22
|
+
#endif
|
23
|
+
#ifdef SIGTRAP
|
24
|
+
{"TRAP", SIGTRAP},
|
25
|
+
#endif
|
26
|
+
#ifdef SIGIOT
|
27
|
+
{"IOT", SIGIOT},
|
28
|
+
#endif
|
29
|
+
#ifdef SIGABRT
|
30
|
+
{"ABRT", SIGABRT},
|
31
|
+
#endif
|
32
|
+
#ifdef SIGEMT
|
33
|
+
{"EMT", SIGEMT},
|
34
|
+
#endif
|
35
|
+
#ifdef SIGFPE
|
36
|
+
{"FPE", SIGFPE},
|
37
|
+
#endif
|
38
|
+
#ifdef SIGKILL
|
39
|
+
{"KILL", SIGKILL},
|
40
|
+
#endif
|
41
|
+
#ifdef SIGBUS
|
42
|
+
{"BUS", SIGBUS},
|
43
|
+
#endif
|
44
|
+
#ifdef SIGSEGV
|
45
|
+
{"SEGV", SIGSEGV},
|
46
|
+
#endif
|
47
|
+
#ifdef SIGSYS
|
48
|
+
{"SYS", SIGSYS},
|
49
|
+
#endif
|
50
|
+
#ifdef SIGPIPE
|
51
|
+
{"PIPE", SIGPIPE},
|
52
|
+
#endif
|
53
|
+
#ifdef SIGALRM
|
54
|
+
{"ALRM", SIGALRM},
|
55
|
+
#endif
|
56
|
+
#ifdef SIGTERM
|
57
|
+
{"TERM", SIGTERM},
|
58
|
+
#endif
|
59
|
+
#ifdef SIGURG
|
60
|
+
{"URG", SIGURG},
|
61
|
+
#endif
|
62
|
+
#ifdef SIGSTOP
|
63
|
+
{"STOP", SIGSTOP},
|
64
|
+
#endif
|
65
|
+
#ifdef SIGTSTP
|
66
|
+
{"TSTP", SIGTSTP},
|
67
|
+
#endif
|
68
|
+
#ifdef SIGCONT
|
69
|
+
{"CONT", SIGCONT},
|
70
|
+
#endif
|
71
|
+
#ifdef SIGCHLD
|
72
|
+
{"CHLD", SIGCHLD},
|
73
|
+
#endif
|
74
|
+
#ifdef SIGCLD
|
75
|
+
{"CLD", SIGCLD},
|
76
|
+
#else
|
77
|
+
# ifdef SIGCHLD
|
78
|
+
{"CLD", SIGCHLD},
|
79
|
+
# endif
|
80
|
+
#endif
|
81
|
+
#ifdef SIGTTIN
|
82
|
+
{"TTIN", SIGTTIN},
|
83
|
+
#endif
|
84
|
+
#ifdef SIGTTOU
|
85
|
+
{"TTOU", SIGTTOU},
|
86
|
+
#endif
|
87
|
+
#ifdef SIGIO
|
88
|
+
{"IO", SIGIO},
|
89
|
+
#endif
|
90
|
+
#ifdef SIGXCPU
|
91
|
+
{"XCPU", SIGXCPU},
|
92
|
+
#endif
|
93
|
+
#ifdef SIGXFSZ
|
94
|
+
{"XFSZ", SIGXFSZ},
|
95
|
+
#endif
|
96
|
+
#ifdef SIGVTALRM
|
97
|
+
{"VTALRM", SIGVTALRM},
|
98
|
+
#endif
|
99
|
+
#ifdef SIGPROF
|
100
|
+
{"PROF", SIGPROF},
|
101
|
+
#endif
|
102
|
+
#ifdef SIGWINCH
|
103
|
+
{"WINCH", SIGWINCH},
|
104
|
+
#endif
|
105
|
+
#ifdef SIGUSR1
|
106
|
+
{"USR1", SIGUSR1},
|
107
|
+
#endif
|
108
|
+
#ifdef SIGUSR2
|
109
|
+
{"USR2", SIGUSR2},
|
110
|
+
#endif
|
111
|
+
#ifdef SIGLOST
|
112
|
+
{"LOST", SIGLOST},
|
113
|
+
#endif
|
114
|
+
#ifdef SIGMSG
|
115
|
+
{"MSG", SIGMSG},
|
116
|
+
#endif
|
117
|
+
#ifdef SIGPWR
|
118
|
+
{"PWR", SIGPWR},
|
119
|
+
#endif
|
120
|
+
#ifdef SIGPOLL
|
121
|
+
{"POLL", SIGPOLL},
|
122
|
+
#endif
|
123
|
+
#ifdef SIGDANGER
|
124
|
+
{"DANGER", SIGDANGER},
|
125
|
+
#endif
|
126
|
+
#ifdef SIGMIGRATE
|
127
|
+
{"MIGRATE", SIGMIGRATE},
|
128
|
+
#endif
|
129
|
+
#ifdef SIGPRE
|
130
|
+
{"PRE", SIGPRE},
|
131
|
+
#endif
|
132
|
+
#ifdef SIGGRANT
|
133
|
+
{"GRANT", SIGGRANT},
|
134
|
+
#endif
|
135
|
+
#ifdef SIGRETRACT
|
136
|
+
{"RETRACT", SIGRETRACT},
|
137
|
+
#endif
|
138
|
+
#ifdef SIGSOUND
|
139
|
+
{"SOUND", SIGSOUND},
|
140
|
+
#endif
|
141
|
+
#ifdef SIGINFO
|
142
|
+
{"INFO", SIGINFO},
|
143
|
+
#endif
|
144
|
+
{NULL, 0}
|
145
|
+
};
|
146
|
+
|
147
|
+
static int
|
148
|
+
signm2signo(const char *nm)
|
149
|
+
{
|
150
|
+
const struct signals *sigs;
|
151
|
+
|
152
|
+
for (sigs = siglist; sigs->signm; sigs++)
|
153
|
+
if (strcmp(sigs->signm, nm) == 0)
|
154
|
+
return sigs->signo;
|
155
|
+
return 0;
|
156
|
+
}
|
157
|
+
|
158
|
+
static const char*
|
159
|
+
signo2signm(int no)
|
160
|
+
{
|
161
|
+
const struct signals *sigs;
|
162
|
+
|
163
|
+
for (sigs = siglist; sigs->signm; sigs++)
|
164
|
+
if (sigs->signo == no)
|
165
|
+
return sigs->signm;
|
166
|
+
return 0;
|
167
|
+
}
|
168
|
+
|
169
|
+
static int
|
170
|
+
trap_signm(VALUE vsig)
|
171
|
+
{
|
172
|
+
int sig = -1;
|
173
|
+
const char *s;
|
174
|
+
|
175
|
+
switch (TYPE(vsig)) {
|
176
|
+
case T_FIXNUM:
|
177
|
+
sig = FIX2INT(vsig);
|
178
|
+
if (sig < 0 || sig >= NSIG) {
|
179
|
+
rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
|
180
|
+
}
|
181
|
+
break;
|
182
|
+
|
183
|
+
case T_SYMBOL:
|
184
|
+
s = rb_id2name(SYM2ID(vsig));
|
185
|
+
if (!s) rb_raise(rb_eArgError, "bad signal");
|
186
|
+
goto str_signal;
|
187
|
+
|
188
|
+
default:
|
189
|
+
s = StringValuePtr(vsig);
|
190
|
+
|
191
|
+
str_signal:
|
192
|
+
if (strncmp("SIG", s, 3) == 0)
|
193
|
+
s += 3;
|
194
|
+
sig = signm2signo(s);
|
195
|
+
if (sig == 0 && strcmp(s, "EXIT") != 0)
|
196
|
+
rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
|
197
|
+
}
|
198
|
+
return sig;
|
199
|
+
}
|
200
|
+
|
201
|
+
// TODO do something here
|
202
|
+
static void
|
203
|
+
default_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
|
204
|
+
{
|
205
|
+
|
206
|
+
}
|
207
|
+
|
208
|
+
static void
|
209
|
+
ignore_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
|
210
|
+
{
|
211
|
+
|
212
|
+
}
|
213
|
+
|
214
|
+
static void
|
215
|
+
exit_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
|
216
|
+
{
|
217
|
+
exit(watcher->signum);
|
218
|
+
}
|
219
|
+
|
220
|
+
static void
|
221
|
+
block_cb(struct ev_loop *loop, ev_signal *watcher, int revents)
|
222
|
+
{
|
223
|
+
signal_data *data = watcher->data;
|
224
|
+
VALUE rv;
|
225
|
+
|
226
|
+
rv = rb_funcall(data->block, rb_intern("call"), 1, INT2FIX(watcher->signum));
|
227
|
+
|
228
|
+
if (rv == Qfalse) {
|
229
|
+
ev_signal_stop(loop, watcher);
|
230
|
+
rb_gc_unregister_address(&data->block);
|
231
|
+
free(data);
|
232
|
+
free(watcher);
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
static VALUE
|
237
|
+
sig_trap(int argc, VALUE *argv)
|
238
|
+
{
|
239
|
+
ev_signal *watcher;
|
240
|
+
VALUE cmd;
|
241
|
+
signal_data *data;
|
242
|
+
int sign;
|
243
|
+
|
244
|
+
rb_secure(2);
|
245
|
+
|
246
|
+
if (argc < 1 || argc > 2)
|
247
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
|
248
|
+
|
249
|
+
sign = trap_signm(argv[0]);
|
250
|
+
watcher = ALLOC(ev_signal);
|
251
|
+
|
252
|
+
if (argc == 1) {
|
253
|
+
data = ALLOC(signal_data);
|
254
|
+
data->block = rb_block_proc();
|
255
|
+
watcher->data = data;
|
256
|
+
rb_gc_register_address(&data->block);
|
257
|
+
ev_signal_init(watcher, block_cb, sign);
|
258
|
+
} else {
|
259
|
+
cmd = argv[1];
|
260
|
+
if (OBJ_TAINTED(cmd))
|
261
|
+
rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
|
262
|
+
if (!NIL_P(cmd)) {
|
263
|
+
switch (RSTRING_LEN(cmd)) {
|
264
|
+
case 0:
|
265
|
+
goto sig_ign;
|
266
|
+
break;
|
267
|
+
case 14:
|
268
|
+
if (strncmp(RSTRING_PTR(cmd), "SYSTEM_DEFAULT", 14) == 0) {
|
269
|
+
sig_dfl:
|
270
|
+
ev_signal_init(watcher, default_cb, sign);
|
271
|
+
}
|
272
|
+
break;
|
273
|
+
case 7:
|
274
|
+
if (strncmp(RSTRING_PTR(cmd), "SIG_IGN", 7) == 0) {
|
275
|
+
sig_ign:
|
276
|
+
ev_signal_init(watcher, ignore_cb, sign);
|
277
|
+
}
|
278
|
+
else if (strncmp(RSTRING_PTR(cmd), "SIG_DFL", 7) == 0) {
|
279
|
+
goto sig_dfl;
|
280
|
+
}
|
281
|
+
else if (strncmp(RSTRING_PTR(cmd), "DEFAULT", 7) == 0) {
|
282
|
+
goto sig_dfl;
|
283
|
+
}
|
284
|
+
break;
|
285
|
+
case 6:
|
286
|
+
if (strncmp(RSTRING_PTR(cmd), "IGNORE", 6) == 0)
|
287
|
+
goto sig_ign;
|
288
|
+
break;
|
289
|
+
case 4:
|
290
|
+
if (strncmp(RSTRING_PTR(cmd), "EXIT", 4) == 0) {
|
291
|
+
ev_signal_init(watcher, exit_cb, sign);
|
292
|
+
}
|
293
|
+
break;
|
294
|
+
}
|
295
|
+
}
|
296
|
+
}
|
297
|
+
|
298
|
+
ev_signal_start(loop, watcher);
|
299
|
+
return Qnil;
|
300
|
+
}
|
301
|
+
|
302
|
+
void
|
303
|
+
init_signal(VALUE module)
|
304
|
+
{
|
305
|
+
VALUE signal_module = rb_define_module_under(module, "Signal");
|
306
|
+
|
307
|
+
rb_define_module_function(signal_module, "trap", sig_trap, -1);
|
308
|
+
}
|
data/lib/evio.rb
ADDED
data/lib/evio/signal.rb
ADDED
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thiago de Arruda
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description:
|
31
|
+
email: tpadilha84@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions:
|
34
|
+
- ext/evio/extconf.rb
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/evio/signal.rb
|
38
|
+
- lib/evio.rb
|
39
|
+
- ext/evio/ev.c
|
40
|
+
- ext/evio/evio.c
|
41
|
+
- ext/evio/io.c
|
42
|
+
- ext/evio/signal.c
|
43
|
+
- ext/evio/evio.h
|
44
|
+
- ext/evio/extconf.rb
|
45
|
+
homepage: http://rubygems.org/gems/evio
|
46
|
+
licenses: []
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.8.23
|
66
|
+
signing_key:
|
67
|
+
specification_version: 3
|
68
|
+
summary: Simple non-blocking IO
|
69
|
+
test_files: []
|