mirror of
https://github.com/janet-lang/janet
synced 2024-12-28 17:30:31 +00:00
Do not explicitly free state machines, instead return a status.
This makes it harder to have some kind of use after free issue.
This commit is contained in:
parent
117ae196fd
commit
a78af0a7fb
2
Makefile
2
Makefile
@ -136,7 +136,7 @@ BOOT_CFLAGS:=-DJANET_BOOTSTRAP -DJANET_BUILD=$(JANET_BUILD) $(CFLAGS)
|
||||
|
||||
$(JANET_BOOT_OBJECTS): $(JANET_BOOT_HEADERS)
|
||||
|
||||
build/%.boot.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS)
|
||||
build/%.boot.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile
|
||||
$(CC) $(BOOT_CFLAGS) -o $@ -c $<
|
||||
|
||||
build/janet_boot: $(JANET_BOOT_OBJECTS)
|
||||
|
@ -343,7 +343,7 @@ JanetListenerState *janet_listen(JanetPollable *pollable, JanetListener behavior
|
||||
}
|
||||
|
||||
/* Tell system we are done listening for a certain event */
|
||||
void janet_unlisten(JanetListenerState *state) {
|
||||
static void janet_unlisten(JanetListenerState *state) {
|
||||
JanetPollable *pollable = state->pollable;
|
||||
int is_last = (state->_next == NULL && pollable->state == state);
|
||||
int op = is_last ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
|
||||
@ -401,11 +401,15 @@ void janet_loop1_impl(void) {
|
||||
int mask = events[i].events;
|
||||
JanetListenerState *state = pollable->state;
|
||||
while (NULL != state) {
|
||||
JanetListenerState *next_state = state->_next;
|
||||
JanetAsyncStatus status = JANET_ASYNC_STATUS_NOT_DONE;
|
||||
if (mask & EPOLLOUT)
|
||||
state->machine(state, JANET_ASYNC_EVENT_WRITE);
|
||||
if (mask & EPOLLIN)
|
||||
state->machine(state, JANET_ASYNC_EVENT_READ);
|
||||
state = state->_next;
|
||||
status = state->machine(state, JANET_ASYNC_EVENT_WRITE);
|
||||
if (status == JANET_ASYNC_STATUS_NOT_DONE && (mask & EPOLLIN))
|
||||
status = state->machine(state, JANET_ASYNC_EVENT_READ);
|
||||
if (status == JANET_ASYNC_STATUS_DONE)
|
||||
janet_unlisten(state);
|
||||
state = next_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ typedef struct {
|
||||
int is_chunk;
|
||||
} NetStateRead;
|
||||
|
||||
void net_machine_read(JanetListenerState *s, int event) {
|
||||
JanetAsyncStatus net_machine_read(JanetListenerState *s, JanetAsyncEvent event) {
|
||||
NetStateRead *state = (NetStateRead *) s;
|
||||
switch (event) {
|
||||
default:
|
||||
@ -159,7 +159,7 @@ void net_machine_read(JanetListenerState *s, int event) {
|
||||
case JANET_ASYNC_EVENT_CLOSE:
|
||||
/* Read is finished, even if chunk is incomplete */
|
||||
janet_schedule(s->fiber, janet_wrap_nil());
|
||||
break;
|
||||
return JANET_ASYNC_STATUS_DONE;
|
||||
case JANET_ASYNC_EVENT_READ:
|
||||
/* Read in bytes */
|
||||
{
|
||||
@ -187,11 +187,12 @@ void net_machine_read(JanetListenerState *s, int event) {
|
||||
if (!state->is_chunk || bytes_left == 0) {
|
||||
Janet resume_val = nread > 0 ? janet_wrap_buffer(buffer) : janet_wrap_nil();
|
||||
janet_schedule(s->fiber, resume_val);
|
||||
janet_unlisten(s);
|
||||
return JANET_ASYNC_STATUS_DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return JANET_ASYNC_STATUS_NOT_DONE;
|
||||
}
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes) {
|
||||
@ -226,7 +227,7 @@ typedef struct {
|
||||
int is_buffer;
|
||||
} NetStateWrite;
|
||||
|
||||
void net_machine_write(JanetListenerState *s, int event) {
|
||||
JanetAsyncStatus net_machine_write(JanetListenerState *s, JanetAsyncEvent event) {
|
||||
NetStateWrite *state = (NetStateWrite *) s;
|
||||
switch (event) {
|
||||
default:
|
||||
@ -238,7 +239,7 @@ void net_machine_write(JanetListenerState *s, int event) {
|
||||
break;
|
||||
case JANET_ASYNC_EVENT_CLOSE:
|
||||
janet_schedule(s->fiber, janet_wrap_nil());
|
||||
break;
|
||||
return JANET_ASYNC_STATUS_DONE;
|
||||
case JANET_ASYNC_EVENT_WRITE: {
|
||||
int32_t start, len;
|
||||
const uint8_t *bytes;
|
||||
@ -266,12 +267,13 @@ void net_machine_write(JanetListenerState *s, int event) {
|
||||
state->start = start;
|
||||
if (start >= len) {
|
||||
janet_schedule(s->fiber, janet_wrap_nil());
|
||||
janet_unlisten(s);
|
||||
return JANET_ASYNC_STATUS_DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return JANET_ASYNC_STATUS_NOT_DONE;
|
||||
}
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_write_buffer(JanetStream *stream, JanetBuffer *buf) {
|
||||
@ -302,7 +304,7 @@ typedef struct {
|
||||
JanetFunction *function;
|
||||
} NetStateSimpleServer;
|
||||
|
||||
void net_machine_simple_server(JanetListenerState *s, int event) {
|
||||
JanetAsyncStatus net_machine_simple_server(JanetListenerState *s, JanetAsyncEvent event) {
|
||||
NetStateSimpleServer *state = (NetStateSimpleServer *) s;
|
||||
switch (event) {
|
||||
default:
|
||||
@ -317,7 +319,7 @@ void net_machine_simple_server(JanetListenerState *s, int event) {
|
||||
case JANET_ASYNC_EVENT_CLOSE:
|
||||
janet_schedule(s->fiber, janet_wrap_nil());
|
||||
janet_gcunroot(janet_wrap_abstract(s->pollable));
|
||||
break;
|
||||
return JANET_ASYNC_STATUS_DONE;
|
||||
case JANET_ASYNC_EVENT_READ: {
|
||||
JSock connfd = accept(s->pollable->handle, NULL, NULL);
|
||||
if (JSOCKVALID(connfd)) {
|
||||
@ -330,6 +332,7 @@ void net_machine_simple_server(JanetListenerState *s, int event) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return JANET_ASYNC_STATUS_NOT_DONE;
|
||||
}
|
||||
|
||||
/* Adress info */
|
||||
|
@ -1142,13 +1142,21 @@ extern enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT];
|
||||
#ifdef JANET_EV
|
||||
#define JANET_POLL_FLAG_CLOSED 0x1
|
||||
#define JANET_POLL_FLAG_SOCKET 0x2
|
||||
#define JANET_ASYNC_EVENT_INIT 0
|
||||
#define JANET_ASYNC_EVENT_MARK 1
|
||||
#define JANET_ASYNC_EVENT_DEINIT 2
|
||||
#define JANET_ASYNC_EVENT_CLOSE 3
|
||||
#define JANET_ASYNC_EVENT_READ 4
|
||||
#define JANET_ASYNC_EVENT_WRITE 5
|
||||
#define JANET_ASYNC_EVENT_TIMEOUT 6
|
||||
|
||||
typedef enum {
|
||||
JANET_ASYNC_EVENT_INIT,
|
||||
JANET_ASYNC_EVENT_MARK,
|
||||
JANET_ASYNC_EVENT_DEINIT,
|
||||
JANET_ASYNC_EVENT_CLOSE,
|
||||
JANET_ASYNC_EVENT_READ,
|
||||
JANET_ASYNC_EVENT_WRITE,
|
||||
JANET_ASYNC_EVENT_TIMEOUT
|
||||
} JanetAsyncEvent;
|
||||
|
||||
typedef enum {
|
||||
JANET_ASYNC_STATUS_NOT_DONE,
|
||||
JANET_ASYNC_STATUS_DONE
|
||||
} JanetAsyncStatus;
|
||||
|
||||
/* Typedefs */
|
||||
#ifdef JANET_WINDOWS
|
||||
@ -1158,7 +1166,7 @@ typedef int JanetPollType;
|
||||
#endif
|
||||
typedef struct JanetListenerState JanetListenerState;
|
||||
typedef struct JanetPollable JanetPollable;
|
||||
typedef void (*JanetListener)(JanetListenerState *state, int event);
|
||||
typedef JanetAsyncStatus(*JanetListener)(JanetListenerState *state, JanetAsyncEvent event);
|
||||
|
||||
/* Wrapper around file descriptors and HANDLEs that can be polled. */
|
||||
struct JanetPollable {
|
||||
@ -1192,7 +1200,6 @@ JANET_API void janet_schedule(JanetFiber *fiber, Janet value);
|
||||
|
||||
/* Start a state machine listening for events from a pollable */
|
||||
JANET_API JanetListenerState *janet_listen(JanetPollable *pollable, JanetListener behavior, int mask, size_t size);
|
||||
JANET_API void janet_unlisten(JanetListenerState *state);
|
||||
|
||||
/* Shorthand for yielding to event loop in C */
|
||||
JANET_NO_RETURN JANET_API void janet_await(void);
|
||||
|
Loading…
Reference in New Issue
Block a user