home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / security / ylonen-ssh / ssh-rsync-wrapper < prev    next >
Text File  |  2000-05-22  |  3KB  |  102 lines

  1.  
  2.  
  3.  
  4. Re: ssh often hangs where pserver succeeds
  5. To: gcc at gcc dot gnu dot org 
  6. Subject: Re: ssh often hangs where pserver succeeds 
  7. From: thospel at mail dot dma dot be (Ton Hospel) 
  8. Date: 5 May 2000 02:20:48 GMT 
  9. Organization: lunix confusion services 
  10. References: <200005030930.CAA04062@gkm-dsl-194.ascend.com> <20000503081408.A22257@lucon.org> 
  11. Xref: Home.Lunix mail.ecgs:34644 
  12.  
  13.  
  14. In article <20000503081408.A22257@lucon.org>, "H . J . Lu" <hjl@lucon.org> writes:
  15.  
  16. > On Wed, May 03, 2000 at 02:30:55AM -0700, Greg McGary wrote:
  17. >> FYI...
  18. >> 
  19. >> I have noticed that cvs over ssh often hangs, especially for
  20. >> long-running diffs and updates.  Running without locks via `cvs -n'
  21. >> helps for diffs, but doesn't work correctly for updates.  On a whim I
  22. >> reverted to pserver and so far it has succeeded every time where ssh
  23. >> had been hanging.
  24. >> 
  25. >> Has anyone else experienced hangs with cvs over ssh?
  26. > I heard rsync hangs over ssh.
  27.  
  28. I had the same problem on an rsync where I had extended the protocol a
  29. bit. (not sure if standard rsync can also trigger it). I traced back the
  30. rare (happened about 1 in a hundred times) errors to a classic deadlock
  31. were rsync was blocked trying to write to ssh, and ssh was blocked trying
  32. to write to rsync. The deadlock is very sensitive to your exact network
  33. speeds and buffer settings.
  34.  
  35. Rsync is a pure read then write then read protocol, but ssh does in fact do
  36. a clean select on stdin/stdout and buffering of pending data. But it forgets
  37. to put the filedescriptors in non blocking mode. So I tend to call ssh the
  38. cause (though there's no reason for rsync to not put it's pipes in non-block
  39. to give the slave program an extra chance).
  40.  
  41. I never contributed my patch to ssh since I stopped helping them after they
  42. unfreed their copyright (thereby stealing the code of mine already in it).
  43.  
  44. Compile the following wrapper, and put it in the same directary as you have
  45. ssh. Tell your rsync to use this unblock_ssh program. If it solves your
  46. problem, then you were running into this same deadlock.
  47.  
  48. ---------------------------
  49. /* Written by Ton Hospel */
  50. /* Hereby put under GNU copyleft */
  51.  
  52. #include <stdio.h>
  53. #include <string.h>
  54. #include <strings.h>
  55. #include <stdlib.h>
  56. #include <errno.h>
  57. #ifndef HAVE_NO_UNISTD_H
  58. # include <unistd.h>
  59. #endif /* HAVE_NO_UNISTD_H */
  60. #include <fcntl.h>
  61.  
  62. static char ssh[] = "ssh";
  63.  
  64. int main(int argc, char **argv) {
  65.     int rc;
  66.     char *ptr, *work;
  67.  
  68.     rc = fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
  69.     if (rc < 0) {
  70.         fprintf(stderr, "Could not unblock stdin: %s\n", strerror(errno));
  71.         return 1;
  72.     }
  73.     rc = fcntl(fileno(stdout), F_SETFL, O_NONBLOCK);
  74.     if (rc < 0) {
  75.         fprintf(stderr, "Could not unblock stdout: %s\n", strerror(errno));
  76.         return 1;
  77.     }
  78.     rc = fcntl(fileno(stderr), F_SETFL, O_NONBLOCK);
  79.     if (rc < 0) {
  80.         fprintf(stderr, "Could not unblock stderr: %s\n", strerror(errno));
  81.         return 1;
  82.     }
  83.     
  84.     ptr = rindex(argv[0], '/');
  85.     if (ptr == NULL) ptr = argv[0];
  86.     else ptr++;
  87.     work = malloc(ptr-argv[0]+sizeof(ssh));
  88.     if (!work) {
  89.         fprintf(stderr, "Out of memory. Buy more ?\n");
  90.         return 1;
  91.     }
  92.     memcpy(work, argv[0], ptr-argv[0]);
  93.     memcpy(work+(ptr-argv[0]), ssh, sizeof(ssh));
  94.     argv[0] = work;
  95.     rc = execvp(work, argv);
  96.     fprintf(stderr, "Could not exec %.300s: %s\n", work, strerror(errno));
  97.     return rc;
  98. }
  99.  
  100.