diff options
author | Peter Harris <pharris@opentext.com> | 2021-02-01 19:45:28 -0500 |
---|---|---|
committer | Peter Harris <pharris@opentext.com> | 2021-06-04 14:31:13 +0000 |
commit | 21414e7c447f18224c577ed5e32bd5d6e45c44f9 (patch) | |
tree | 0002140c8f51e0cf23d186f6f6a3ec362586addd /src/c_client.py | |
parent | 4b0d9d3868aad8d5f4266821e9eda586e6c2bfa7 (diff) |
Fix writev emulation on Windows
There are at least two bugs in the previous implementation:
- If an early iovec is partially written, there can be a gap of missing
data (as a later iovec will be started before the early iovec is
completed).
- If a late iovec returns WSAEWOULDBLOCK, *vector and *count are not
updated, leading to a re-send of the entire request.
Move the *vector update into the send() loop to update piecemeal as
individual iovecs are sent.
Example program that demonstrates the issue (this program should run
forever after these bugs have been fixed):
#include <stdio.h>
#include <stdlib.h>
#include "xcb.h"
// Non-cryptographic random number generator from http://burtleburtle.net/bob/rand/smallprng.html
// because Microsoft's random number generators either have a too small RAND_MAX or are too slow
typedef struct ranctx { uint32_t a; uint32_t b; uint32_t c; uint32_t d; } ranctx;
static uint32_t ranval(ranctx *x);
static void raninit(ranctx *x, uint32_t seed);
#define MAX_PROP_LEN (128 * 1024)
int main(int argc, char *argv[]) {
uint32_t seed = 0x12345678;
if (argc > 1) {
seed = strtoul(argv[1], NULL, 0);
}
ranctx ran;
raninit(&ran, seed);
xcb_connection_t *c = xcb_connect(NULL, NULL);
if (!c || xcb_connection_has_error(c)) {
printf("Cannot connect to $DISPLAY\n");
return 1;
}
const xcb_setup_t *setup = xcb_get_setup(c);
char *buf = malloc(MAX_PROP_LEN + 8); // plus a bit of slack so we can run random values off the end
if (!buf) {
printf("oom\n");
return 1;
}
for (uint32_t i=0; i < (MAX_PROP_LEN + 3) / 4; i++) {
((uint32_t *)buf)[i] = ranval(&ran);
}
xcb_window_t win = xcb_generate_id(c);
xcb_create_window(c, 0, win, xcb_setup_roots_iterator(setup).data[0].root, 0, 0, 1, 1, 0,
XCB_WINDOW_CLASS_INPUT_ONLY, 0, 0, NULL);
printf("Created window 0x%X\n", win);
for (;;) {
xcb_flush(c);
xcb_generic_event_t *ev = xcb_poll_for_event(c);
if (ev) {
if (ev->response_type == 0) {
xcb_generic_error_t *err = (xcb_generic_error_t *)ev;
printf("Unexpected X Error %d\n", err->error_code);
printf(" Sequence %d\n", err->sequence);
printf(" Resource ID 0x%X\n", err->resource_id);
printf(" Opcode: %d.%d\n", err->major_code, err->minor_code);
return 1;
}
printf("Unexpected X Event %d\n", ev->response_type);
return 1;
}
uint32_t siz = ranval(&ran) % MAX_PROP_LEN + 1;
xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, XCB_ATOM_STRING, XCB_ATOM_STRING, 8, siz, buf);
}
return 0;
}
#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
static uint32_t ranval(ranctx *x) {
uint32_t e = x->a - rot(x->b, 27);
x->a = x->b ^ rot(x->c, 17);
x->b = x->c + x->d;
x->c = x->d + e;
x->d = e + x->a;
return x->d;
}
static void raninit(ranctx *x, uint32_t seed) {
uint32_t i;
x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
for (i = 0; i<20; ++i) {
(void)ranval(x);
}
}
Signed-off-by: Peter Harris <pharris@opentext.com>
Diffstat (limited to 'src/c_client.py')
0 files changed, 0 insertions, 0 deletions