Skip to content

Commit fddb0a9

Browse files
woodpeckhummeltech
andauthored
ensure that partial reads from recv don't trip up rendering (#469)
* ensure that partial reads from recv don't trip up rendering * Fixed logic & applied styling standard * Now that we are allowing `short reads`, we need to not re-zero `resp` in the loop * We need to cast `&resp` for the `recv` call in order to advance the memory address as expected * We should handle `EINTR` `errno`s * We need to break if an unexpected response type/etc. is received * In order to later prevent following the `if (ret <=0)` path --------- Co-authored-by: David Hummel <6109326+hummeltech@users.noreply.github.com>
1 parent a032b72 commit fddb0a9

1 file changed

Lines changed: 33 additions & 16 deletions

File tree

src/mod_tile.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -379,37 +379,54 @@ static int request_tile(request_rec *r, struct protocol *cmd, int renderImmediat
379379
struct pollfd rx;
380380
int s;
381381

382+
size_t already_read = 0;
383+
size_t want = sizeof(struct protocol_v2);
384+
bzero(&resp, sizeof(struct protocol));
385+
382386
while (1) {
383387
rx.fd = fd;
384388
rx.events = POLLIN;
385389
s = poll(&rx, 1, timeout * 1000);
386390

387391
if (s > 0) {
388-
bzero(&resp, sizeof(struct protocol));
389-
ret = recv(fd, &resp, sizeof(struct protocol_v2), 0);
392+
ret = recv(fd, (char *)&resp + already_read, want - already_read, 0);
393+
394+
// a return value of <= 0 means that there is some kind of error or EOF
395+
if (ret <= 0) {
396+
// handle interrupted system calls gracefully
397+
if (ret == -1 && errno == EINTR) {
398+
continue;
399+
}
390400

391-
if (ret != sizeof(struct protocol_v2)) {
392-
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "request_tile: Failed to read response from rendering socket. Got %d bytes but expected %d. Errno %d (%s)",
393-
ret, (int)sizeof(struct protocol_v2), errno, strerror(errno));
401+
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "request_tile: Failed to read response from rendering socket: %s",
402+
strerror(errno));
394403
break;
395404
}
396405

397-
if (resp.ver == 3) {
398-
ret += recv(fd, ((void *)&resp) + sizeof(struct protocol_v2), sizeof(struct protocol) - sizeof(struct protocol_v2), 0);
406+
// other return values mean that some bytes were read, not necessary as many as we wanted
407+
already_read += ret;
408+
409+
// first integer in message is protocol version
410+
if (already_read >= sizeof(int)) {
411+
want = (resp.ver == 3) ? sizeof(struct protocol) : sizeof(struct protocol_v2);
399412
}
400413

401-
if (cmd->x == resp.x && cmd->y == resp.y && cmd->z == resp.z && !strcmp(cmd->xmlname, resp.xmlname)) {
402-
close(fd);
414+
// do we have a complete packet?
415+
if (already_read == want) {
416+
if (cmd->x == resp.x && cmd->y == resp.y && cmd->z == resp.z && !strcmp(cmd->xmlname, resp.xmlname)) {
417+
close(fd);
403418

404-
if (resp.cmd == cmdDone) {
405-
return 1;
419+
if (resp.cmd == cmdDone) {
420+
return 1;
421+
} else {
422+
return 0;
423+
}
406424
} else {
407-
return 0;
425+
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
426+
"Response does not match request: xml(%s,%s) z(%d,%d) x(%d,%d) y(%d,%d)", cmd->xmlname,
427+
resp.xmlname, cmd->z, resp.z, cmd->x, resp.x, cmd->y, resp.y);
428+
break;
408429
}
409-
} else {
410-
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
411-
"Response does not match request: xml(%s,%s) z(%d,%d) x(%d,%d) y(%d,%d)", cmd->xmlname,
412-
resp.xmlname, cmd->z, resp.z, cmd->x, resp.x, cmd->y, resp.y);
413430
}
414431
} else if (s == 0) {
415432
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,

0 commit comments

Comments
 (0)