Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/io/io.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Delegatory functions that assert we have a capable handle, then delegate
4
 * through the IO table to the correct operation. */
5
6
12.0k
static MVMOSHandle * verify_is_handle(MVMThreadContext *tc, MVMObject *oshandle, const char *op) {
7
12.0k
    if (REPR(oshandle)->ID != MVM_REPR_ID_MVMOSHandle)
8
0
        MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle (got %s with REPR %s)", op, STABLE(oshandle)->debug_name, REPR(oshandle)->name);
9
12.0k
    return (MVMOSHandle *)oshandle;
10
12.0k
}
11
12
12.0k
static uv_mutex_t * acquire_mutex(MVMThreadContext *tc, MVMOSHandle *handle) {
13
12.0k
    uv_mutex_t *mutex = handle->body.mutex;
14
12.0k
    uv_mutex_lock(mutex);
15
12.0k
    MVM_tc_set_ex_release_mutex(tc, mutex);
16
12.0k
    return mutex;
17
12.0k
}
18
19
12.0k
static void release_mutex(MVMThreadContext *tc, uv_mutex_t *mutex) {
20
12.0k
    uv_mutex_unlock(mutex);
21
12.0k
    MVM_tc_clear_ex_release_mutex(tc);
22
12.0k
}
23
24
201
MVMint64 MVM_io_close(MVMThreadContext *tc, MVMObject *oshandle) {
25
201
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "close");
26
201
    if (handle->body.ops->closable) {
27
201
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
28
201
        MVMint64 ret = handle->body.ops->closable->close(tc, handle);
29
201
        release_mutex(tc, mutex);
30
201
        return ret;
31
201
    }
32
201
    else
33
0
        MVM_exception_throw_adhoc(tc, "Cannot close this kind of handle");
34
201
}
35
36
1
MVMint64 MVM_io_is_tty(MVMThreadContext *tc, MVMObject *oshandle) {
37
1
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "istty");
38
1
    /* We need the extra check on is_tty because it is NULL for pipes. */
39
1
    if (handle->body.ops->introspection && handle->body.ops->introspection->is_tty) {
40
1
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
41
1
        MVMint64 ret = handle->body.ops->introspection->is_tty(tc, handle);
42
1
        release_mutex(tc, mutex);
43
1
        return ret;
44
1
    }
45
0
    else {
46
0
        return 0;
47
0
    }
48
1
}
49
50
0
MVMint64 MVM_io_fileno(MVMThreadContext *tc, MVMObject *oshandle) {
51
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "get native descriptor");
52
0
    if (handle->body.ops->introspection) {
53
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
54
0
        MVMint64 ret = handle->body.ops->introspection->native_descriptor(tc, handle);
55
0
        release_mutex(tc, mutex);
56
0
        return ret;
57
0
    }
58
0
    else {
59
0
        return -1;
60
0
    }
61
0
}
62
63
163
void MVM_io_set_encoding(MVMThreadContext *tc, MVMObject *oshandle, MVMString *encoding_name) {
64
163
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set encoding");
65
163
    MVMROOT(tc, handle, {
66
163
        const MVMuint8 encoding_flag = MVM_string_find_encoding(tc, encoding_name);
67
163
        if (handle->body.ops->encodable) {
68
163
            uv_mutex_t *mutex = acquire_mutex(tc, handle);
69
163
            handle->body.ops->encodable->set_encoding(tc, handle, encoding_flag);
70
163
            release_mutex(tc, mutex);
71
163
        }
72
163
        else
73
163
            MVM_exception_throw_adhoc(tc, "Cannot set encoding on this kind of handle");
74
163
    });
75
163
}
76
77
6
void MVM_io_seek(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 offset, MVMint64 flag) {
78
6
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "seek");
79
6
    if (handle->body.ops->seekable) {
80
6
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
81
6
        handle->body.ops->seekable->seek(tc, handle, offset, flag);
82
6
        release_mutex(tc, mutex);
83
6
    }
84
6
    else
85
0
        MVM_exception_throw_adhoc(tc, "Cannot seek this kind of handle");
86
6
}
87
88
9
MVMint64 MVM_io_tell(MVMThreadContext *tc, MVMObject *oshandle) {
89
9
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "tell");
90
9
    if (handle->body.ops->seekable) {
91
9
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
92
9
        MVMint64 result = handle->body.ops->seekable->tell(tc, handle);
93
9
        release_mutex(tc, mutex);
94
9
        return result;
95
9
    }
96
9
    else
97
0
        MVM_exception_throw_adhoc(tc, "Cannot tell this kind of handle");
98
9
}
99
100
7
void MVM_io_set_separator(MVMThreadContext *tc, MVMObject *oshandle, MVMString *sep) {
101
7
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set separator");
102
7
    if (handle->body.ops->sync_readable) {
103
7
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
104
7
        handle->body.ops->sync_readable->set_separator(tc, handle, &sep, 1);
105
7
        release_mutex(tc, mutex);
106
7
    }
107
7
    else
108
0
        MVM_exception_throw_adhoc(tc, "Cannot set a separator on this kind of handle");
109
7
}
110
111
6
void MVM_io_set_separators(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *seps) {
112
6
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "set separators");
113
6
    if (handle->body.ops->sync_readable) {
114
6
        MVMint32 is_str_array = REPR(seps)->pos_funcs.get_elem_storage_spec(tc,
115
6
            STABLE(seps)).boxed_primitive == MVM_STORAGE_SPEC_BP_STR;
116
6
        if (is_str_array) {
117
6
            uv_mutex_t *mutex;
118
6
            MVMString **c_seps;
119
6
            MVMuint64 i;
120
6
121
6
            MVMuint64 num_seps = MVM_repr_elems(tc, seps);
122
6
            if (num_seps > 0xFFFFFF)
123
0
                MVM_exception_throw_adhoc(tc, "Too many line separators");
124
6
            c_seps = MVM_malloc((num_seps ? num_seps : 1) * sizeof(MVMString *));
125
18
            for (i = 0; i < num_seps; i++)
126
12
                c_seps[i] = MVM_repr_at_pos_s(tc, seps, i);
127
6
128
6
            mutex = acquire_mutex(tc, handle);
129
6
            handle->body.ops->sync_readable->set_separator(tc, handle, c_seps, (MVMint32)num_seps);
130
6
            release_mutex(tc, mutex);
131
6
132
6
            MVM_free(c_seps);
133
6
        }
134
0
        else {
135
0
            MVM_exception_throw_adhoc(tc, "Set separators requires a native string array");
136
0
        }
137
6
    }
138
0
    else {
139
0
        MVM_exception_throw_adhoc(tc, "Cannot set separators on this kind of handle");
140
0
    }
141
6
}
142
143
26
MVMString * MVM_io_readline(MVMThreadContext *tc, MVMObject *oshandle, MVMint32 chomp) {
144
26
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "readline");
145
26
    if (handle->body.ops->sync_readable) {
146
26
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
147
26
        MVMString *result = handle->body.ops->sync_readable->read_line(tc, handle, chomp);
148
26
        release_mutex(tc, mutex);
149
26
        return result;
150
26
    }
151
26
    else
152
0
        MVM_exception_throw_adhoc(tc, "Cannot read lines from this kind of handle");
153
26
}
154
155
4
MVMString * MVM_io_read_string(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 chars) {
156
4
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read string");
157
4
    if (handle->body.ops->sync_readable) {
158
4
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
159
4
        MVMString *result = handle->body.ops->sync_readable->read_chars(tc, handle, chars);
160
4
        release_mutex(tc, mutex);
161
4
        return result;
162
4
    }
163
4
    else
164
0
        MVM_exception_throw_adhoc(tc, "Cannot read characters from this kind of handle");
165
4
}
166
167
4
void MVM_io_read_bytes(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *result, MVMint64 length) {
168
4
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read bytes");
169
4
    MVMint64 bytes_read;
170
4
    char *buf;
171
4
172
4
    /* Ensure the target is in the correct form. */
173
4
    if (!IS_CONCRETE(result) || REPR(result)->ID != MVM_REPR_ID_VMArray)
174
0
        MVM_exception_throw_adhoc(tc, "read_fhb requires a native array to write to");
175
4
    if (((MVMArrayREPRData *)STABLE(result)->REPR_data)->slot_type != MVM_ARRAY_U8
176
2
        && ((MVMArrayREPRData *)STABLE(result)->REPR_data)->slot_type != MVM_ARRAY_I8)
177
0
        MVM_exception_throw_adhoc(tc, "read_fhb requires a native array of uint8 or int8");
178
4
179
4
    if (length < 1)
180
0
        MVM_exception_throw_adhoc(tc, "Out of range: attempted to read %"PRId64" bytes from filehandle", length);
181
4
182
4
    if (handle->body.ops->sync_readable) {
183
4
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
184
4
        bytes_read = handle->body.ops->sync_readable->read_bytes(tc, handle, &buf, length);
185
4
        release_mutex(tc, mutex);
186
4
    }
187
4
    else
188
0
        MVM_exception_throw_adhoc(tc, "Cannot read characters from this kind of handle");
189
4
190
4
    /* Stash the data in the VMArray. */
191
4
    ((MVMArray *)result)->body.slots.i8 = (MVMint8 *)buf;
192
4
    ((MVMArray *)result)->body.start    = 0;
193
4
    ((MVMArray *)result)->body.ssize    = bytes_read;
194
4
    ((MVMArray *)result)->body.elems    = bytes_read;
195
4
}
196
197
176
MVMString * MVM_io_slurp(MVMThreadContext *tc, MVMObject *oshandle) {
198
176
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "slurp");
199
176
    if (handle->body.ops->sync_readable) {
200
176
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
201
176
        MVMString *result = handle->body.ops->sync_readable->slurp(tc, handle);
202
176
        release_mutex(tc, mutex);
203
176
        return result;
204
176
    }
205
176
    else
206
0
        MVM_exception_throw_adhoc(tc, "Cannot slurp this kind of handle");
207
176
}
208
209
11.4k
MVMint64 MVM_io_write_string(MVMThreadContext *tc, MVMObject *oshandle, MVMString *str, MVMint8 addnl) {
210
11.4k
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string");
211
11.4k
    if (str == NULL)
212
0
        MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given");
213
11.4k
    if (handle->body.ops->sync_writable) {
214
11.4k
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
215
11.4k
        MVMint64 result = handle->body.ops->sync_writable->write_str(tc, handle, str, addnl);
216
11.4k
        release_mutex(tc, mutex);
217
11.4k
        return result;
218
11.4k
    }
219
11.4k
    else
220
0
        MVM_exception_throw_adhoc(tc, "Cannot write a string to this kind of handle");
221
11.4k
}
222
223
2
void MVM_io_write_bytes(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *buffer) {
224
2
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write bytes");
225
2
    char *output;
226
2
    MVMint64 output_size;
227
2
228
2
    /* Ensure the target is in the correct form. */
229
2
    if (!IS_CONCRETE(buffer) || REPR(buffer)->ID != MVM_REPR_ID_VMArray)
230
0
        MVM_exception_throw_adhoc(tc, "write_fhb requires a native array to read from");
231
2
    if (((MVMArrayREPRData *)STABLE(buffer)->REPR_data)->slot_type != MVM_ARRAY_U8
232
0
        && ((MVMArrayREPRData *)STABLE(buffer)->REPR_data)->slot_type != MVM_ARRAY_I8)
233
0
        MVM_exception_throw_adhoc(tc, "write_fhb requires a native array of uint8 or int8");
234
2
235
2
    output = (char *)(((MVMArray *)buffer)->body.slots.i8 + ((MVMArray *)buffer)->body.start);
236
2
    output_size = ((MVMArray *)buffer)->body.elems;
237
2
238
2
    if (handle->body.ops->sync_writable) {
239
2
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
240
2
        handle->body.ops->sync_writable->write_bytes(tc, handle, output, output_size);
241
2
        release_mutex(tc, mutex);
242
2
    }
243
2
    else
244
0
        MVM_exception_throw_adhoc(tc, "Cannot write bytes to this kind of handle");
245
2
}
246
247
MVMObject * MVM_io_read_chars_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
248
0
                                    MVMObject *schedulee, MVMObject *async_type) {
249
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read chars asynchronously");
250
0
    if (handle->body.ops->async_readable) {
251
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
252
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_readable->read_chars(tc,
253
0
            handle, queue, schedulee, async_type);
254
0
        release_mutex(tc, mutex);
255
0
        return result;
256
0
    }
257
0
    else
258
0
        MVM_exception_throw_adhoc(tc, "Cannot read chars asynchronously from this kind of handle");
259
0
}
260
261
MVMObject * MVM_io_read_bytes_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
262
0
                                    MVMObject *schedulee, MVMObject *buf_type, MVMObject *async_type) {
263
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "read bytes asynchronously");
264
0
    if (handle->body.ops->async_readable) {
265
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
266
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_readable->read_bytes(tc,
267
0
            handle, queue, schedulee, buf_type, async_type);
268
0
        release_mutex(tc, mutex);
269
0
        return result;
270
0
    }
271
0
    else
272
0
        MVM_exception_throw_adhoc(tc, "Cannot read bytes asynchronously from this kind of handle");
273
0
}
274
275
MVMObject * MVM_io_write_string_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
276
0
                                      MVMObject *schedulee, MVMString *str, MVMObject *async_type) {
277
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string asynchronously");
278
0
    if (str == NULL)
279
0
        MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given");
280
0
    if (handle->body.ops->async_writable) {
281
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
282
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_writable->write_str(tc,
283
0
            handle, queue, schedulee, str, async_type);
284
0
        release_mutex(tc, mutex);
285
0
        return result;
286
0
    }
287
0
    else
288
0
        MVM_exception_throw_adhoc(tc, "Cannot write a string asynchronously to this kind of handle");
289
0
}
290
291
MVMObject * MVM_io_write_bytes_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
292
0
                                     MVMObject *schedulee, MVMObject *buffer, MVMObject *async_type) {
293
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write buffer asynchronously");
294
0
    if (buffer == NULL)
295
0
        MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL buffer given");
296
0
    if (handle->body.ops->async_writable) {
297
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
298
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_writable->write_bytes(tc,
299
0
            handle, queue, schedulee, buffer, async_type);
300
0
        release_mutex(tc, mutex);
301
0
        return result;
302
0
    }
303
0
    else
304
0
        MVM_exception_throw_adhoc(tc, "Cannot write bytes asynchronously to this kind of handle");
305
0
}
306
307
MVMObject * MVM_io_write_string_to_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
308
                                         MVMObject *schedulee, MVMString *str, MVMObject *async_type,
309
0
                                         MVMString *host, MVMint64 port) {
310
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write string asynchronously to destination");
311
0
    if (str == NULL)
312
0
        MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL string given");
313
0
    if (handle->body.ops->async_writable_to) {
314
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
315
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_writable_to->write_str_to(tc,
316
0
            handle, queue, schedulee, str, async_type, host, port);
317
0
        release_mutex(tc, mutex);
318
0
        return result;
319
0
    }
320
0
    else
321
0
        MVM_exception_throw_adhoc(tc, "Cannot write a string to a destination asynchronously to this kind of handle");
322
0
}
323
324
MVMObject * MVM_io_write_bytes_to_async(MVMThreadContext *tc, MVMObject *oshandle, MVMObject *queue,
325
                                        MVMObject *schedulee, MVMObject *buffer, MVMObject *async_type,
326
0
                                        MVMString *host, MVMint64 port) {
327
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "write buffer asynchronously to destination");
328
0
    if (buffer == NULL)
329
0
        MVM_exception_throw_adhoc(tc, "Failed to write to filehandle: NULL buffer given");
330
0
    if (handle->body.ops->async_writable_to) {
331
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
332
0
        MVMObject *result = (MVMObject *)handle->body.ops->async_writable_to->write_bytes_to(tc,
333
0
            handle, queue, schedulee, buffer, async_type, host, port);
334
0
        release_mutex(tc, mutex);
335
0
        return result;
336
0
    }
337
0
    else
338
0
        MVM_exception_throw_adhoc(tc, "Cannot write bytes to a destination asynchronously to this kind of handle");
339
0
}
340
341
3
MVMint64 MVM_io_eof(MVMThreadContext *tc, MVMObject *oshandle) {
342
3
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "eof");
343
3
    if (handle->body.ops->sync_readable) {
344
3
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
345
3
        MVMint64 result = handle->body.ops->sync_readable->eof(tc, handle);
346
3
        release_mutex(tc, mutex);
347
3
        return result;
348
3
    }
349
3
    else
350
0
        MVM_exception_throw_adhoc(tc, "Cannot eof this kind of handle");
351
3
}
352
353
0
MVMint64 MVM_io_lock(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 flag) {
354
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "lock");
355
0
    if (handle->body.ops->lockable) {
356
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
357
0
        MVMint64 result = handle->body.ops->lockable->lock(tc, handle, flag);
358
0
        release_mutex(tc, mutex);
359
0
        return result;
360
0
    }
361
0
    else
362
0
        MVM_exception_throw_adhoc(tc, "Cannot lock this kind of handle");
363
0
}
364
365
0
void MVM_io_unlock(MVMThreadContext *tc, MVMObject *oshandle) {
366
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "unlock");
367
0
    if (handle->body.ops->lockable) {
368
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
369
0
        handle->body.ops->lockable->unlock(tc, handle);
370
0
        release_mutex(tc, mutex);
371
0
    }
372
0
    else
373
0
        MVM_exception_throw_adhoc(tc, "Cannot unlock this kind of handle");
374
0
}
375
376
0
void MVM_io_flush(MVMThreadContext *tc, MVMObject *oshandle) {
377
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "flush");
378
0
    if (handle->body.ops->sync_writable) {
379
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
380
0
        handle->body.ops->sync_writable->flush(tc, handle);
381
0
        release_mutex(tc, mutex);
382
0
    }
383
0
    else
384
0
        MVM_exception_throw_adhoc(tc, "Cannot flush this kind of handle");
385
0
}
386
387
0
void MVM_io_truncate(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 offset) {
388
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "truncate");
389
0
    if (handle->body.ops->sync_writable) {
390
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
391
0
        handle->body.ops->sync_writable->truncate(tc, handle, offset);
392
0
        release_mutex(tc, mutex);
393
0
    }
394
0
    else
395
0
        MVM_exception_throw_adhoc(tc, "Cannot truncate this kind of handle");
396
0
}
397
398
0
void MVM_io_connect(MVMThreadContext *tc, MVMObject *oshandle, MVMString *host, MVMint64 port) {
399
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "connect");
400
0
    if (handle->body.ops->sockety) {
401
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
402
0
        handle->body.ops->sockety->connect(tc, handle, host, port);
403
0
        release_mutex(tc, mutex);
404
0
    }
405
0
    else
406
0
        MVM_exception_throw_adhoc(tc, "Cannot connect this kind of handle");
407
0
}
408
409
0
void MVM_io_bind(MVMThreadContext *tc, MVMObject *oshandle, MVMString *host, MVMint64 port, MVMint32 backlog) {
410
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "bind");
411
0
    if (handle->body.ops->sockety) {
412
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
413
0
        handle->body.ops->sockety->bind(tc, handle, host, port, backlog);
414
0
        release_mutex(tc, mutex);
415
0
    }
416
0
    else
417
0
        MVM_exception_throw_adhoc(tc, "Cannot bind this kind of handle");
418
0
}
419
420
0
MVMObject * MVM_io_accept(MVMThreadContext *tc, MVMObject *oshandle) {
421
0
    MVMOSHandle *handle = verify_is_handle(tc, oshandle, "accept");
422
0
    if (handle->body.ops->sockety) {
423
0
        uv_mutex_t *mutex = acquire_mutex(tc, handle);
424
0
        MVMObject *result = handle->body.ops->sockety->accept(tc, handle);
425
0
        release_mutex(tc, mutex);
426
0
        return result;
427
0
    }
428
0
    else
429
0
        MVM_exception_throw_adhoc(tc, "Cannot accept this kind of handle");
430
0
}