Re: Another rsync over ssh hang (repeatable, with 2.4.1 on both ends)

Ton Hospel (linux-kernel@ton.iguana.be)
Sun, 4 Mar 2001 21:28:45 +0000 (UTC)


Notice also that by default ssh opens stdin/stdout blocking, and can
relatively easily deadlock if the pipes it talks over really want to do
a write before a read or the other way round.

You can try compile the following file, put it in the same directory
as ssh, and then run rsync over this instead of plain ssh (I use it in
fact in all places where I connect to ssh over pipes).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#ifndef HAVE_NO_UNISTD_H
# include <unistd.h>
#endif /* HAVE_NO_UNISTD_H */
#include <fcntl.h>

static char ssh[] = "ssh";

int unblock(FILE *fp) {
int fd, rc, flags;

fd = fileno(fp);
if (isatty(fd)) return 0;

flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
fprintf(stderr, "Could not query fd %d: %s\n", fd, strerror(errno));
return 1;
}
rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if (rc < 0) {
fprintf(stderr, "Could not unblock fd %d: %s\n", fd, strerror(errno));
return 1;
}
return 0;
}

int main(int argc, char **argv) {
int rc;
char *ptr, *work;

if (unblock(stdin)) return 1;
if (unblock(stdout)) return 1;
if (unblock(stderr)) return 1;

ptr = strrchr(argv[0], '/');
if (ptr == NULL) ptr = argv[0];
else ptr++;
work = malloc(ptr-argv[0]+sizeof(ssh));
if (!work) {
fprintf(stderr, "Out of memory. Buy more ?\n");
return 1;
}
memcpy(work, argv[0], ptr-argv[0]);
memcpy(work+(ptr-argv[0]), ssh, sizeof(ssh));
argv[0] = work;
rc = execvp(work, argv);
fprintf(stderr, "Could not exec %.300s: %s\n", work, strerror(errno));
return rc;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/