mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-04-04 07:15:53 -04:00
tests: Fix race condition in send overflow test
This change ensures that the compositor process is not able to respond to any of the noop requests sent by the client process, by using the test compositor's `stop_display` mechanism to coordinate when the compositor should stop processing messages. (Before this change, it was possible that one of the calls of wl_event_loop_dispatch in the compositor process could respond to all the client's noop requests before returning.) Signed-off-by: Manuel Stoeckl <code@mstoeckl.com>
This commit is contained in:
parent
555d3b8a9b
commit
e449232f37
3 changed files with 32 additions and 13 deletions
|
|
@ -1431,6 +1431,9 @@ send_overflow_client(void *data)
|
||||||
int *pipes = data;
|
int *pipes = data;
|
||||||
char tmp = '\0';
|
char tmp = '\0';
|
||||||
|
|
||||||
|
/* Request to break out of 'display_run' in the main process */
|
||||||
|
assert(stop_display(c, 1) >= 0);
|
||||||
|
|
||||||
/* On Linux, the Unix socket default buffer size is <=256KB, and
|
/* On Linux, the Unix socket default buffer size is <=256KB, and
|
||||||
* each noop request requires 8 bytes; the buffer should thus
|
* each noop request requires 8 bytes; the buffer should thus
|
||||||
* overflow within about 32K /unhandled/ iterations */
|
* overflow within about 32K /unhandled/ iterations */
|
||||||
|
|
@ -1457,7 +1460,7 @@ TEST(send_overflow_disconnection)
|
||||||
struct display *d;
|
struct display *d;
|
||||||
char tmp;
|
char tmp;
|
||||||
int rpipe[2];
|
int rpipe[2];
|
||||||
int i;
|
ssize_t ret;
|
||||||
|
|
||||||
assert(pipe(rpipe) != -1);
|
assert(pipe(rpipe) != -1);
|
||||||
|
|
||||||
|
|
@ -1469,16 +1472,18 @@ TEST(send_overflow_disconnection)
|
||||||
* interrupted if the client dies */
|
* interrupted if the client dies */
|
||||||
close(rpipe[1]);
|
close(rpipe[1]);
|
||||||
|
|
||||||
/* At least 2 loops of this are needed to respond for the client to
|
/* Run the display until the client sends a `stop_display`, then
|
||||||
* set up the test interface */
|
* send a resume message but don't actually look at new messages */
|
||||||
for (i = 0; i < 5; i++) {
|
display_run(d);
|
||||||
wl_display_flush_clients(d->wl_display);
|
display_post_resume_events(d);
|
||||||
wl_event_loop_dispatch(wl_display_get_event_loop(d->wl_display), -1);
|
wl_display_flush_clients(d->wl_display);
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until all noop requests have been sent, or until client
|
/* Wait until all noop requests have been sent (read returns 1), or
|
||||||
* process aborts */
|
* until client process aborts (read returns 0) */
|
||||||
(void)read(rpipe[0], &tmp, sizeof(tmp));
|
do {
|
||||||
|
ret = read(rpipe[0], &tmp, sizeof(tmp));
|
||||||
|
} while (ret == -1 && errno == EINTR);
|
||||||
|
assert(ret != -1);
|
||||||
close(rpipe[0]);
|
close(rpipe[0]);
|
||||||
|
|
||||||
/* For a clean shutdown */
|
/* For a clean shutdown */
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,7 @@ display_run(struct display *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
display_resume(struct display *d)
|
display_post_resume_events(struct display *d)
|
||||||
{
|
{
|
||||||
struct wfr *wfr, *next;
|
struct wfr *wfr, *next;
|
||||||
|
|
||||||
|
|
@ -380,7 +380,12 @@ display_resume(struct display *d)
|
||||||
|
|
||||||
assert(wl_list_empty(&d->waiting_for_resume));
|
assert(wl_list_empty(&d->waiting_for_resume));
|
||||||
d->wfr_num = 0;
|
d->wfr_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
display_resume(struct display *d)
|
||||||
|
{
|
||||||
|
display_post_resume_events(d);
|
||||||
wl_display_run(d->wl_display);
|
wl_display_run(d->wl_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,21 @@ struct display *display_create(void);
|
||||||
void display_destroy(struct display *d);
|
void display_destroy(struct display *d);
|
||||||
void display_run(struct display *d);
|
void display_run(struct display *d);
|
||||||
|
|
||||||
|
/* This function posts the display_resumed event to all waiting clients,
|
||||||
|
* so that after flushing events the clients will stop waiting and continue.
|
||||||
|
*
|
||||||
|
* (Calling `display_run` after this function will resume the display loop.)
|
||||||
|
*/
|
||||||
|
void display_post_resume_events(struct display *d);
|
||||||
/* After n clients called stop_display(..., n), the display
|
/* After n clients called stop_display(..., n), the display
|
||||||
* is stopped and can process the code after display_run().
|
* is stopped and can process the code after display_run().
|
||||||
* This function rerun the display again and send display_resumed
|
*
|
||||||
* event to waiting clients, so the clients will stop waiting and continue */
|
* This function posts the display_resumed event to the waiting
|
||||||
|
* clients, so that the clients will stop waiting and continue;
|
||||||
|
* it then reruns the display. */
|
||||||
void display_resume(struct display *d);
|
void display_resume(struct display *d);
|
||||||
|
|
||||||
|
|
||||||
struct client_info *client_create_with_name(struct display *d,
|
struct client_info *client_create_with_name(struct display *d,
|
||||||
void (*client_main)(void *data),
|
void (*client_main)(void *data),
|
||||||
void *data,
|
void *data,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue