semian 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/ext/semian/semian.c +17 -9
- data/lib/semian.rb +2 -0
- data/lib/semian/version.rb +3 -0
- data/semian.gemspec +5 -1
- data/test/test_semian.rb +20 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85e7688d4e7394755e61fe1223f33646a9245f69
|
4
|
+
data.tar.gz: fc55fda5e5799267fc81f3fed586117f62762dc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f04b5bc23920ab15e8fb1a73890a66a7ce4719e8286eff31170506460680853dfc302cfc4683eeb33c03cf168b72f7ef9f235a16a66ace28456026ddd60e00bb
|
7
|
+
data.tar.gz: 2eed26a9736cd3114b172bce7ecbd7cfa77d6ef8601acd78ba18ea7c166c6b2fa7103e2cd78b74d9f30b2c75a3229934a198dbf8881529b452ba6b03e10cb75a
|
data/Gemfile.lock
CHANGED
data/ext/semian/semian.c
CHANGED
@@ -23,7 +23,7 @@ typedef VALUE (*my_blocking_fn_t)(void*);
|
|
23
23
|
#endif
|
24
24
|
|
25
25
|
static ID id_timeout;
|
26
|
-
static VALUE eTimeout;
|
26
|
+
static VALUE eSyscall, eTimeout;
|
27
27
|
|
28
28
|
typedef struct {
|
29
29
|
int sem_id;
|
@@ -48,6 +48,12 @@ ms_to_timespec(long ms, struct timespec *ts)
|
|
48
48
|
ts->tv_nsec = (ms % 1000) * 1000000;
|
49
49
|
}
|
50
50
|
|
51
|
+
static void
|
52
|
+
raise_semian_syscall_error(const char *syscall, int error_num)
|
53
|
+
{
|
54
|
+
rb_raise(eSyscall, "%s failed, errno: %d (%s)", syscall, error_num, strerror(error_num));
|
55
|
+
}
|
56
|
+
|
51
57
|
static void
|
52
58
|
semian_resource_mark(void *ptr)
|
53
59
|
{
|
@@ -128,12 +134,12 @@ semian_resource_initialize(VALUE self, VALUE id, VALUE tickets, VALUE default_ti
|
|
128
134
|
|
129
135
|
res->sem_id = semget(key, 1, flags);
|
130
136
|
if (res->sem_id == -1) {
|
131
|
-
|
137
|
+
raise_semian_syscall_error("semget()", errno);
|
132
138
|
}
|
133
139
|
|
134
140
|
if (FIX2LONG(tickets) != 0
|
135
141
|
&& semctl(res->sem_id, 0, SETVAL, FIX2LONG(tickets)) == -1) {
|
136
|
-
|
142
|
+
raise_semian_syscall_error("semctl()", errno);
|
137
143
|
}
|
138
144
|
|
139
145
|
return self;
|
@@ -144,7 +150,7 @@ cleanup_semian_resource_acquire(VALUE self)
|
|
144
150
|
{
|
145
151
|
semian_resource_t *res = NULL;
|
146
152
|
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, res);
|
147
|
-
struct sembuf buf = { 0, 1,
|
153
|
+
struct sembuf buf = { 0, 1, SEM_UNDO };
|
148
154
|
if (semop(res->sem_id, &buf, 1) == -1) {
|
149
155
|
res->error = errno;
|
150
156
|
}
|
@@ -195,7 +201,7 @@ semian_resource_acquire(int argc, VALUE *argv, VALUE self)
|
|
195
201
|
if (res.error == EAGAIN) {
|
196
202
|
rb_raise(eTimeout, "timed out waiting for resource '%s'", res.name);
|
197
203
|
} else {
|
198
|
-
|
204
|
+
raise_semian_syscall_error("semop()", res.error);
|
199
205
|
}
|
200
206
|
}
|
201
207
|
|
@@ -209,7 +215,7 @@ semian_resource_destroy(VALUE self)
|
|
209
215
|
|
210
216
|
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, res);
|
211
217
|
if (semctl(res->sem_id, 0, IPC_RMID) == -1) {
|
212
|
-
|
218
|
+
raise_semian_syscall_error("semctl()", errno);
|
213
219
|
}
|
214
220
|
|
215
221
|
return Qtrue;
|
@@ -224,7 +230,7 @@ semian_resource_count(VALUE self)
|
|
224
230
|
TypedData_Get_Struct(self, semian_resource_t, &semian_resource_type, res);
|
225
231
|
ret = semctl(res->sem_id, 0, GETVAL);
|
226
232
|
if (ret == -1) {
|
227
|
-
|
233
|
+
raise_semian_syscall_error("semctl()", errno);
|
228
234
|
}
|
229
235
|
|
230
236
|
return LONG2FIX(ret);
|
@@ -232,11 +238,13 @@ semian_resource_count(VALUE self)
|
|
232
238
|
|
233
239
|
void Init_semian()
|
234
240
|
{
|
235
|
-
VALUE cSemian, cResource;
|
241
|
+
VALUE cSemian, cResource, eBaseError;
|
236
242
|
|
237
243
|
cSemian = rb_define_class("Semian", rb_cObject);
|
238
244
|
cResource = rb_define_class("Resource", cSemian);
|
239
|
-
|
245
|
+
eBaseError = rb_define_class_under(cSemian, "BaseError", rb_eStandardError);
|
246
|
+
eSyscall = rb_define_class_under(cSemian, "SyscallError", eBaseError);
|
247
|
+
eTimeout = rb_define_class_under(cSemian, "TimeoutError", eBaseError);
|
240
248
|
|
241
249
|
rb_define_alloc_func(cResource, semian_resource_alloc);
|
242
250
|
rb_define_method(cResource, "initialize", semian_resource_initialize, 3);
|
data/lib/semian.rb
CHANGED
data/semian.gemspec
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'semian/version'
|
4
|
+
|
1
5
|
Gem::Specification.new do |s|
|
2
6
|
s.name = 'semian'
|
3
|
-
s.version =
|
7
|
+
s.version = Semian::VERSION
|
4
8
|
s.summary = 'SysV semaphore based library for shared resource control'
|
5
9
|
s.description = <<-DOC
|
6
10
|
A Ruby C extention that is used to control access to shared resources
|
data/test/test_semian.rb
CHANGED
@@ -5,7 +5,7 @@ require 'fileutils'
|
|
5
5
|
|
6
6
|
class TestSemian < Test::Unit::TestCase
|
7
7
|
def setup
|
8
|
-
Semian[:testing].destroy rescue
|
8
|
+
Semian[:testing].destroy rescue Semian::BaseError
|
9
9
|
end
|
10
10
|
|
11
11
|
def test_register_invalid_args
|
@@ -22,7 +22,7 @@ class TestSemian < Test::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_register_with_no_tickets_raises
|
25
|
-
assert_raises
|
25
|
+
assert_raises Semian::SyscallError do
|
26
26
|
Semian.register :testing
|
27
27
|
end
|
28
28
|
end
|
@@ -50,7 +50,7 @@ class TestSemian < Test::Unit::TestCase
|
|
50
50
|
t = Thread.start do
|
51
51
|
m.synchronize do
|
52
52
|
cond.wait_until { acquired }
|
53
|
-
assert_raises Semian::
|
53
|
+
assert_raises Semian::TimeoutError do
|
54
54
|
Semian[:testing].acquire { refute true }
|
55
55
|
end
|
56
56
|
end
|
@@ -101,7 +101,7 @@ class TestSemian < Test::Unit::TestCase
|
|
101
101
|
pid = fork do
|
102
102
|
Semian.register :testing, timeout: 0.5
|
103
103
|
Semian[:testing].acquire do
|
104
|
-
assert_raises Semian::
|
104
|
+
assert_raises Semian::TimeoutError do
|
105
105
|
Semian[:testing].acquire { }
|
106
106
|
end
|
107
107
|
end
|
@@ -129,7 +129,7 @@ class TestSemian < Test::Unit::TestCase
|
|
129
129
|
end
|
130
130
|
|
131
131
|
sleep 0.1 until File.exists?(path)
|
132
|
-
assert_raises Semian::
|
132
|
+
assert_raises Semian::TimeoutError do
|
133
133
|
Semian[:testing].acquire {}
|
134
134
|
end
|
135
135
|
|
@@ -155,10 +155,24 @@ class TestSemian < Test::Unit::TestCase
|
|
155
155
|
assert acquired
|
156
156
|
end
|
157
157
|
|
158
|
+
def test_sem_undo
|
159
|
+
Semian.register :testing, tickets: 1
|
160
|
+
|
161
|
+
# Ensure we don't hit ERANGE errors caused by lack of SEM_UNDO on semop* calls
|
162
|
+
# by doing an acquire > SEMVMX (32767) times:
|
163
|
+
#
|
164
|
+
# See: http://lxr.free-electrons.com/source/ipc/sem.c?v=3.8#L419
|
165
|
+
(1 << 16).times do # do an acquire 64k times
|
166
|
+
Semian[:testing].acquire do
|
167
|
+
1
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
158
172
|
def test_destroy
|
159
173
|
Semian.register :testing, tickets: 1
|
160
174
|
Semian[:testing].destroy
|
161
|
-
assert_raises
|
175
|
+
assert_raises Semian::SyscallError do
|
162
176
|
Semian[:testing].acquire { }
|
163
177
|
end
|
164
178
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Francis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- ext/semian/extconf.rb
|
44
44
|
- ext/semian/semian.c
|
45
45
|
- lib/semian.rb
|
46
|
+
- lib/semian/version.rb
|
46
47
|
- semian.gemspec
|
47
48
|
- test/test_semian.rb
|
48
49
|
homepage: https://github.com/csfrancis/semian
|