Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 30 additions & 21 deletions test/core/test_poll_blocking.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,41 +22,50 @@ void sleep_ms(int ms) {
usleep(ms * 1000);
}

int64_t timeval_delta_ms(struct timeval* begin, struct timeval* end) {
int64_t delta_s = end->tv_sec - begin->tv_sec;
int64_t delta_us = end->tv_usec - begin->tv_usec;
assert(delta_s >= 0);
return (delta_s * 1000) + (delta_us / 1000);
int64_t timespec_delta_ms(struct timespec* begin, struct timespec* end) {
struct timespec diff = {
.tv_sec = end->tv_sec - begin->tv_sec,
.tv_nsec = end->tv_nsec - begin->tv_nsec
};

if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a negative tv_nsec here not just work in the return calculation below since + (diff.tv_nsec / 1000000) would end up substracting ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about this? I'd love to land this change but maybe this part is not needed?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think.. how about just:

delta_sec = end->tv_sec - begin->tv_sec,
delta_nsec = end->tv_nsec - begin->tv_nsec
return (deleta_sec * 1000) + (delta_nsec / 1000000);

I think the possible negative delta_nsec will be fine here.


assert(diff.tv_sec >= 0);

return (diff.tv_sec * 1000) + (diff.tv_nsec / 1000000);
}

// Check if timeout works without fds
void test_timeout_without_fds() {
printf("test_timeout_without_fds\n");
struct timeval begin, end;
struct timespec begin, end;

gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(poll(NULL, 0, TIMEOUT_MS) == 0);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);
}

// Check if timeout works with fds without events
void test_timeout_with_fds_without_events() {
printf("test_timeout_with_fds_without_events\n");
struct timeval begin, end;
struct timespec begin, end;
int pipe_a[2];

assert(pipe(pipe_a) == 0);

gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
struct pollfd fds = {pipe_a[0], 0, 0};
assert(poll(&fds, 1, TIMEOUT_MS) == 0);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);

Expand All @@ -77,7 +86,7 @@ void *write_after_sleep(void * arg) {
// Check if poll can unblock on an event
void test_unblock_poll() {
printf("test_unblock_poll\n");
struct timeval begin, end;
struct timespec begin, end;
pthread_t tid;
int pipe_a[2];

Expand All @@ -88,13 +97,13 @@ void test_unblock_poll() {
{pipe_a[0], POLLIN, 0},
{pipe_shared[0], POLLIN, 0},
};
gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(pthread_create(&tid, NULL, write_after_sleep, NULL) == 0);
assert(poll(fds, 2, -1) == 1);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);
assert(fds[1].revents & POLLIN);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);

Expand All @@ -105,15 +114,15 @@ void test_unblock_poll() {
}

void *do_poll_in_thread(void * arg) {
struct timeval begin, end;
struct timespec begin, end;

gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
struct pollfd fds = {pipe_shared[0], POLLIN, 0};
assert(poll(&fds, 1, 4000) == 1);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);
assert(fds.revents & POLLIN);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert((duration >= TIMEOUT_MS) && (duration < 4000));

Expand Down
37 changes: 24 additions & 13 deletions test/core/test_poll_blocking_asyncify.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,33 @@

#include <emscripten/eventloop.h>

int64_t timeval_delta_ms(struct timeval* begin, struct timeval* end) {
int64_t delta_s = end->tv_sec - begin->tv_sec;
int64_t delta_us = end->tv_usec - begin->tv_usec;
assert(delta_s >= 0);
return (delta_s * 1000) + (delta_us / 1000);
int64_t timespec_delta_ms(struct timespec* begin, struct timespec* end) {
struct timespec diff = {
.tv_sec = end->tv_sec - begin->tv_sec,
.tv_nsec = end->tv_nsec - begin->tv_nsec
};

if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}

assert(diff.tv_sec >= 0);

return (diff.tv_sec * 1000) + (diff.tv_nsec / 1000000);
}

// Check if timeout works without fds
void test_timeout_without_fds() {
printf("test_timeout_without_fds\n");
struct timeval begin, end;
struct timespec begin = {0};
struct timespec end = {0};

gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(poll(NULL, 0, 1000) == 0);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= 1000);
}
Expand All @@ -51,7 +61,8 @@ void write_to_pipe(void * arg) {
// Check if poll can unblock on an event
void test_unblock_poll() {
printf("test_unblock_poll\n");
struct timeval begin, end;
struct timespec begin = {0};
struct timespec end = {0};
int pipe_a[2];

assert(pipe(pipe_a) == 0);
Expand All @@ -62,12 +73,12 @@ void test_unblock_poll() {
{pipe_shared[0], POLLIN, 0},
};
emscripten_set_timeout(write_to_pipe, 1000, NULL);
gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(poll(fds, 2, -1) == 1);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);
assert(fds[1].revents & POLLIN);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= 1000);

Expand Down
55 changes: 33 additions & 22 deletions test/core/test_select_blocking.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,44 @@ void sleep_ms(int ms) {
usleep(ms * 1000);
}

int64_t timeval_delta_ms(struct timeval* begin, struct timeval* end) {
int64_t delta_s = end->tv_sec - begin->tv_sec;
int64_t delta_us = end->tv_usec - begin->tv_usec;
assert(delta_s >= 0);
return (delta_s * 1000) + (delta_us / 1000);
int64_t timespec_delta_ms(struct timespec* begin, struct timespec* end) {
struct timespec diff = {
.tv_sec = end->tv_sec - begin->tv_sec,
.tv_nsec = end->tv_nsec - begin->tv_nsec
};

if (diff.tv_nsec < 0) {
diff.tv_nsec += 1000000000;
diff.tv_sec -= 1;
}

assert(diff.tv_sec >= 0);

return (diff.tv_sec * 1000) + (diff.tv_nsec / 1000000);
}

// Check if timeout works without fds
void test_timeout_without_fds() {
printf("test_timeout_without_fds\n");
struct timeval tv, begin, end;
struct timespec begin, end;
struct timeval tv;

tv.tv_sec = 0;
tv.tv_usec = TIMEOUT_MS * 1000;
gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(select(0, NULL, NULL, NULL, &tv) == 0);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);
}

// Check if timeout works with fds without events
void test_timeout_with_fds_without_events() {
printf("test_timeout_with_fds_without_events\n");
struct timeval tv, begin, end;
struct timespec begin, end;
struct timeval tv;
fd_set readfds;
int pipe_a[2];

Expand All @@ -55,11 +66,11 @@ void test_timeout_with_fds_without_events() {
tv.tv_usec = TIMEOUT_MS * 1000;
FD_ZERO(&readfds);
FD_SET(pipe_a[0], &readfds);
gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(select(pipe_a[0] + 1, &readfds, NULL, NULL, &tv) == 0);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);

Expand All @@ -80,7 +91,7 @@ void *write_after_sleep(void * arg) {
// Check if select can unblock on an event
void test_unblock_select() {
printf("test_unblock_select\n");
struct timeval begin, end;
struct timespec begin, end;
fd_set readfds;
pthread_t tid;
int pipe_a[2];
Expand All @@ -92,13 +103,13 @@ void test_unblock_select() {
FD_SET(pipe_a[0], &readfds);
FD_SET(pipe_shared[0], &readfds);
int maxfd = (pipe_a[0] > pipe_shared[0] ? pipe_a[0] : pipe_shared[0]);
gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(pthread_create(&tid, NULL, write_after_sleep, NULL) == 0);
assert(select(maxfd + 1, &readfds, NULL, NULL, NULL) == 1);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);
assert(FD_ISSET(pipe_shared[0], &readfds));

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert(duration >= TIMEOUT_MS);

Expand All @@ -109,22 +120,22 @@ void test_unblock_select() {
}

void *do_select_in_thread(void * arg) {
struct timeval begin, end;
fd_set readfds;
struct timespec begin, end;
struct timeval tv;
fd_set readfds;
tv.tv_sec = 4;
tv.tv_usec = 0;

FD_ZERO(&readfds);
FD_SET(pipe_shared[0], &readfds);
int maxfd = pipe_shared[0];

gettimeofday(&begin, NULL);
clock_gettime(CLOCK_MONOTONIC, &begin);
assert(select(maxfd + 1, &readfds, NULL, NULL, &tv) == 1);
gettimeofday(&end, NULL);
clock_gettime(CLOCK_MONOTONIC, &end);
assert(FD_ISSET(pipe_shared[0], &readfds));

int64_t duration = timeval_delta_ms(&begin, &end);
int64_t duration = timespec_delta_ms(&begin, &end);
printf(" -> duration: %lld ms\n", duration);
assert((duration >= TIMEOUT_MS) && (duration < 4000));

Expand Down
3 changes: 0 additions & 3 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9588,17 +9588,14 @@ def test_syscall_intercept(self):
self.do_core_test('test_syscall_intercept.c')

@requires_pthreads
@flaky('https://github.com/emscripten-core/emscripten/issues/26256')
def test_select_blocking(self):
self.do_runf('core/test_select_blocking.c', cflags=['-pthread', '-sPROXY_TO_PTHREAD=1', '-sEXIT_RUNTIME=1'])

@requires_pthreads
@flaky('https://github.com/emscripten-core/emscripten/issues/26256')
def test_poll_blocking(self):
self.do_runf('core/test_poll_blocking.c', cflags=['-pthread', '-sPROXY_TO_PTHREAD=1', '-sEXIT_RUNTIME=1'])

@with_asyncify_and_jspi
@flaky('https://github.com/emscripten-core/emscripten/issues/26256')
def test_poll_blocking_asyncify(self):
if self.get_setting('JSPI') and engine_is_v8(self.get_current_js_engine()):
self.skipTest('test requires setTimeout which is not supported under v8')
Expand Down