evio 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|