Skip to content

Commit 319318a

Browse files
committed
Fix an issue where the stdout of the retried command
was not correctly captured on the second try.
1 parent 8a720e1 commit 319318a

File tree

3 files changed

+97
-63
lines changed

3 files changed

+97
-63
lines changed

ChangeLog

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11

2-
CHanges with v1.0.3
2+
Changes with v1.0.4
3+
4+
*) Fix an issue where the stdout of the retried command
5+
was not correctly captured on the second try. [Graham
6+
Leggett]
7+
8+
Changes with v1.0.3
39

410
*) Switch from help2man to txt2man. [Graham Leggett]
511

configure.ac

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Process this file with autoconf to produce a configure script.
33

44
AC_PREREQ(2.61)
5-
AC_INIT(retry, 1.0.3, minfrin@sharp.fm)
5+
AC_INIT(retry, 1.0.4, minfrin@sharp.fm)
66
AC_CONFIG_AUX_DIR(build-aux)
77
AC_CONFIG_MACRO_DIRS([m4])
88
AM_INIT_AUTOMAKE([dist-bzip2])

retry.c

+89-61
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,17 @@ static struct option long_options[] =
6060
};
6161

6262
typedef struct pump_t {
63+
struct pollfd *rpollfd;
64+
struct pollfd *wpollfd;
6365
void *base;
6466
size_t len;
6567
off_t offset;
68+
int rfd;
69+
int wfd;
6670
int read_closed:1;
6771
int write_closed:1;
6872
int exit_on_close:1;
73+
int no_close:1;
6974
int send_eof:1;
7075
} pump_t;
7176

@@ -232,38 +237,44 @@ static int status_match(int status, const char *criteria)
232237
return 1;
233238
}
234239

235-
static int pump(const char *name, pump_t *pumps, struct pollfd *fds)
240+
static int pump(const char *name, pump_t *pumps)
236241
{
237-
nfds_t nfds = PUMPS * 2;
238242
int i;
239243

240244
while (1) {
241-
int stay = 0;
245+
nfds_t nfds = 0;
246+
struct pollfd fds[PUMPS * 2] = { 0 };
242247

243248
for (i = 0; i < PUMPS; i++) {
244249

245-
fds[OFFSET(i, READ_FD)].events = 0;
246-
fds[OFFSET(i, WRITE_FD)].events = 0;
250+
pumps[i].rpollfd = NULL;
251+
pumps[i].wpollfd = NULL;
247252

248253
if (!pumps[i].read_closed) {
249-
fds[OFFSET(i, READ_FD)].events = POLLIN;
250-
stay = 1;
254+
pumps[i].rpollfd = fds + nfds;
255+
fds[nfds].events = POLLIN;
256+
fds[nfds].fd = pumps[i].rfd;
257+
fds[nfds].revents = 0;
258+
nfds++;
251259
}
252260

253261
if (!pumps[i].write_closed
254262
&& (pumps[i].send_eof || pumps[i].len > pumps[i].offset)) {
255-
fds[OFFSET(i, WRITE_FD)].events = POLLOUT;
256-
stay = 1;
263+
pumps[i].wpollfd = fds + nfds;
264+
fds[nfds].events = POLLOUT;
265+
fds[nfds].fd = pumps[i].wfd;
266+
fds[nfds].revents = 0;
267+
nfds++;
257268
}
258269

259270
if (pumps[i].read_closed && pumps[i].exit_on_close) {
260-
stay = 0;
271+
nfds = 0;
261272
break;
262273
}
263274

264275
}
265276

266-
if (!stay) {
277+
if (!nfds) {
267278
break;
268279
}
269280

@@ -277,77 +288,88 @@ static int pump(const char *name, pump_t *pumps, struct pollfd *fds)
277288

278289
for (i = 0; i < PUMPS; i++) {
279290

280-
if (fds[OFFSET(i, READ_FD)].revents & POLLIN) {
281-
void *base;
282-
ssize_t num;
291+
if (pumps[i].rpollfd) {
283292

284-
base = realloc(pumps[i].base, pumps[i].len + BUFFER_SIZE);
285-
if (!base) {
293+
if (pumps[i].rpollfd->revents & POLLIN) {
294+
void *base;
295+
ssize_t num;
286296

287-
fprintf(stderr, "%s: Out of memory, giving up.\n", name);
297+
base = realloc(pumps[i].base, pumps[i].len + BUFFER_SIZE);
298+
if (!base) {
288299

289-
return -1;
290-
}
291-
pumps[i].base = base;
300+
fprintf(stderr, "%s: Out of memory, giving up.\n",
301+
name);
302+
303+
return -1;
304+
}
305+
pumps[i].base = base;
306+
307+
num = read(pumps[i].rfd, base + pumps[i].len, BUFFER_SIZE);
292308

293-
num = read(fds[OFFSET(i, READ_FD)].fd, base + pumps[i].len, BUFFER_SIZE);
309+
if (num < 0) {
294310

295-
if (num < 0) {
311+
fprintf(stderr, "%s: Could not read, giving up: %s\n",
312+
name, strerror(errno));
296313

297-
fprintf(stderr, "%s: Could not read, giving up: %s\n", name,
298-
strerror(errno));
314+
return -1;
315+
} else if (num == 0) {
316+
pumps[i].read_closed = 1;
317+
pumps[i].send_eof = 1;
318+
close(pumps[i].rfd);
319+
} else {
320+
pumps[i].len += num;
321+
}
299322

300-
return -1;
301323
}
302-
else if (num == 0) {
324+
325+
if ((pumps[i].rpollfd->revents & POLLHUP)
326+
|| (pumps[i].rpollfd->revents & POLLERR)
327+
|| (pumps[i].rpollfd->revents & POLLNVAL)) {
328+
303329
pumps[i].read_closed = 1;
304330
pumps[i].send_eof = 1;
305-
}
306-
else {
307-
pumps[i].len += num;
331+
close(pumps[i].rfd);
332+
308333
}
309334

310335
}
311336

312-
if ((fds[OFFSET(i, READ_FD)].revents & POLLHUP) ||
313-
(fds[OFFSET(i, READ_FD)].revents & POLLERR) ||
314-
(fds[OFFSET(i, READ_FD)].revents & POLLNVAL)) {
315-
316-
pumps[i].read_closed = 1;
317-
pumps[i].send_eof = 1;
337+
if (pumps[i].wpollfd) {
318338

319-
}
339+
if (pumps[i].wpollfd->revents & POLLOUT) {
340+
ssize_t num;
320341

321-
if (fds[OFFSET(i, WRITE_FD)].revents & POLLOUT) {
322-
ssize_t num;
342+
num = write(pumps[i].wfd, pumps[i].base + pumps[i].offset,
343+
pumps[i].len - pumps[i].offset);
323344

324-
num = write(fds[OFFSET(i, WRITE_FD)].fd,
325-
pumps[i].base + pumps[i].offset,
326-
pumps[i].len - pumps[i].offset);
345+
if (num < 0) {
327346

328-
if (num < 0) {
347+
fprintf(stderr, "%s: Could not write, giving up: %s\n",
348+
name, strerror(errno));
329349

330-
fprintf(stderr, "%s: Could not write, giving up: %s\n", name,
331-
strerror(errno));
350+
return -1;
351+
} else {
352+
pumps[i].offset += num;
353+
}
332354

333-
return -1;
334-
}
335-
else {
336-
pumps[i].offset += num;
337-
}
355+
if (pumps[i].read_closed
356+
&& pumps[i].offset == pumps[i].len) {
338357

339-
if (pumps[i].read_closed && pumps[i].offset == pumps[i].len) {
358+
pumps[i].write_closed = 1;
359+
close(pumps[i].wfd);
340360

341-
pumps[i].write_closed = 1;
361+
}
342362

343363
}
344364

345-
}
365+
if ((pumps[i].wpollfd->revents & POLLHUP)
366+
|| (pumps[i].wpollfd->revents & POLLERR)
367+
|| (pumps[i].wpollfd->revents & POLLNVAL)) {
346368

347-
if ((fds[OFFSET(i, WRITE_FD)].revents & POLLERR) ||
348-
(fds[OFFSET(i, WRITE_FD)].revents & POLLNVAL)) {
369+
pumps[i].write_closed = 1;
370+
close(pumps[i].wfd);
349371

350-
pumps[i].write_closed = 1;
372+
}
351373

352374
}
353375

@@ -476,18 +498,17 @@ int main (int argc, char **argv)
476498

477499
/* parent */
478500
else {
479-
struct pollfd fds[PUMPS * 2];
480501

481502
/* handle stdin */
482503

483-
fds[OFFSET(STDIN_FD, READ_FD)].fd = STDIN_FD;
484-
fds[OFFSET(STDIN_FD, WRITE_FD)].fd = inpair[WRITE_FD];
504+
pumps[STDIN_FD].rfd = dup(STDIN_FD);
505+
pumps[STDIN_FD].wfd = inpair[WRITE_FD];
485506
close(inpair[READ_FD]);
486507

487508
/* handle stdout */
488509

489-
fds[OFFSET(STDOUT_FD, READ_FD)].fd = outpair[READ_FD];
490-
fds[OFFSET(STDOUT_FD, WRITE_FD)].fd = STDOUT_FD;
510+
pumps[STDOUT_FD].rfd = outpair[READ_FD];
511+
pumps[STDOUT_FD].wfd = dup(STDOUT_FD);
491512
close(outpair[WRITE_FD]);
492513

493514
/* prevent write to stdout, we will handle it later */
@@ -497,16 +518,19 @@ int main (int argc, char **argv)
497518
pumps[STDOUT_FD].exit_on_close = 1;
498519

499520
/* pump all data */
500-
if (pump(name, pumps, fds)) {
521+
if (pump(name, pumps)) {
501522
status = EXIT_FAILURE;
502523
break;
503524
}
504525

505526
close(inpair[WRITE_FD]);
506527
close(outpair[READ_FD]);
528+
close(pumps[STDIN_FD].rfd);
529+
close(pumps[STDOUT_FD].wfd);
507530

508531
/* reset stdin in case we repeat the command */
509532
pumps[STDIN_FD].offset = 0;
533+
pumps[STDIN_FD].write_closed = 0;
510534

511535
/* wait for the child process to be done */
512536
do {
@@ -543,6 +567,10 @@ int main (int argc, char **argv)
543567
/* failure - write stdout to stderr */
544568
fwrite(pumps[STDOUT_FD].base, pumps[STDOUT_FD].len, 1, stderr);
545569

570+
/* reset stdout for a go-around */
571+
free(pumps[STDOUT_FD].base);
572+
memset(&pumps[STDOUT_FD], 0, sizeof(pump_t));
573+
546574
if (delay) {
547575
fprintf(stderr,
548576
"%s: '%s' returned %d, backing off for %ld second%s and trying again...\n",

0 commit comments

Comments
 (0)