[cvsnt-dev] tentative bugfix: CVSNT 2.5.01.1898 PuTTY/ssh remote
sometimes hangs right at the end
Bjoren Davis
bdweb at mindspring.com
Mon Mar 7 01:00:08 GMT 2005
Dear CVSNT folks,
I have to admit I don't know much about your project, but I
was using CVSNT and I had the problem that sometimes the
thing would hang at the end of an SSH transfer.
It bugged me, and I happened to have the MS VStudio 2003
Trial Edition and the better part of the day to kill, so
I (think) I fixed it.
The source I worked from was cvsnt-2.5.01.1898, and I
used the Microsoft Development Environment 2003 Version 7.1.3088.
Here are the deltas:
diff -cwr cvsnt-2.5.01.1898/plink/plink_cvsnt.c
cvsnt-2.5.01.1898-bkd_hacked/plink/plink_cvsnt.c
*** cvsnt-2.5.01.1898/plink/plink_cvsnt.c Fri Oct 22 17:59:13 2004
--- cvsnt-2.5.01.1898-bkd_hacked/plink/plink_cvsnt.c Sun Mar 6 19:48:48
2005
***************
*** 162,230 ****
static struct output_data *global_odata;
! int plink_read_data(void *buffer, int max_length)
{
! struct output_data *odata = global_odata;
! int todo = max_length,l;
! char *ptr = buffer;
! if(fatal_exit)
return -1;
-
- if(odata->wrap)
- {
- l = odata->len - odata->lenwritten;
-
- if(l <= todo)
- {
- todo -= l;
- memcpy(ptr,odata->buffer+odata->lenwritten,l);
- ptr+=l;
- odata->lenwritten=odata->len;
- odata->writeret = odata->lenwritten;
- odata->wrap=0;
- SetEvent(odata->event);
- if(!todo)
- return 0;
}
! else
! {
! /* Actually, I'm not sure that this case ever happens.. */
! memcpy(ptr,odata->buffer+l,todo);
! ptr+=todo;
! odata->lenwritten+=todo;
return 0;
}
}
! WaitForSingleObject(odata->eventback, INFINITE);
! while(todo)
! {
! if (odata->done)
! break;
! if(odata->len <= (size_t)todo)
! {
! todo -= odata->len;
! memcpy(ptr, odata->buffer, odata->len);
! ptr+=odata->len;
! odata->lenwritten = odata->len;
! odata->writeret = odata->len;
}
! else
! {
! memcpy(ptr, odata->buffer, todo);
! ptr += todo;
! odata->lenwritten = todo;
! odata->wrap=1;
! break;
}
! SetEvent(odata->event);
! if(todo && WaitForSingleObject(odata->eventback, 40)!=WAIT_OBJECT_0)
! break;
}
! return ptr - (char*)buffer;
}
static DWORD WINAPI stderr_write_thread(void *param)
--- 162,255 ----
static struct output_data *global_odata;
! /*
! * Read up to max_length worth of data. This routine will
! * block only if there are no data to read. If anything is
! * available, up to max_length of it will be returned immediately.
! *
! * Rewritten March 6, 2005, Bjoren Davis.
! *
! * I was having problems with cvsnt hanging at the end of
! * some ssh transfers, and I had no idea why. I looked at the
! * old version of this routine, and I really couldn't understand
! * what it was trying to do. It looked as though it was doing
! * a read-and-block-only-if-there's-nothing-but-otherwise-gimme
! * -what-you-got. However, it would block and loop if at the
! * outset of the routine you didn't have any data. Strange.
! * So I wrote the read-and-block-only-if-there's-nothing-but-otherwise-
! * gimme-what-you-got routine you see here.
! */
! int
! plink_read_data(void *buffer, int max_length)
{
! struct output_data *odata;
! int todo, l;
! char *ptr;
!
! odata = global_odata;
! todo = max_length;
! ptr = (char *) buffer;
! /*
! * Loop until we can get something into the return buffer.
! */
! while (TRUE) {
! /*
! * I put the test for fatal_exit here so that it gets checked
! * everytime after we wait.
! */
! if (fatal_exit) {
return -1;
}
!
! if (odata->done) { /* !!!this flag doesn't seem to be set anywhere. */
! odata->writeret = 0;
return 0;
}
+
+ /*
+ * Do we have data, and have we not sent all of it up yet?
+ */
+
+ if (odata->len > 0 && (l = odata->len - odata->lenwritten) > 0) {
+ /* Yes, we have some data to return. */
+
+ /*
+ * If we have fewer data than what's being asked for, then
+ * just settle for what we have.
+ */
+ if (todo > l) {
+ /* we can return at most l bytes right now. */
+ todo = l;
}
! memcpy(ptr, odata->buffer + odata->lenwritten, todo);
! odata->lenwritten += todo;
! l -= todo;
! odata->writeret = todo;
! /*
! * Have we completely drained our supply? If so, then
! * we want to trigger a reload. If not, then we'll
! * fetch more the next time around.
! */
!
! if (l == 0) {
! /* There's nothing left. Trigger the reload. */
!
! SetEvent(odata->event);
}
!
! return todo;
}
!
! /*
! * We're here because we have no data. So wait for some.
! */
! WaitForSingleObject(odata->eventback, INFINITE);
}
! /* NOTREACHED */
}
static DWORD WINAPI stderr_write_thread(void *param)
***************
*** 261,266 ****
--- 286,292 ----
&senddata, &sendlen);
data->buffer = senddata;
data->len = sendlen;
+ data->lenwritten = 0;
SetEvent(data->eventback);
data->busy = 1;
}
***************
*** 436,442 ****
} else if (n == 3) {
edata.busy = 0;
if (!edata.writeret) {
! fprintf(stderr, "Unable to write to standard output\n");
cleanup_exit(0);
}
bufchain_consume(&stderr_data, edata.lenwritten);
--- 462,468 ----
} else if (n == 3) {
edata.busy = 0;
if (!edata.writeret) {
! fprintf(stderr, "Unable to write to standard error\n");
cleanup_exit(0);
}
bufchain_consume(&stderr_data, edata.lenwritten);
***************
*** 598,603 ****
--- 624,630 ----
odata.event = stdoutevent;
odata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
odata.busy = odata.done = 0;
+ odata.len = odata.lenwritten = 0;
global_odata = &odata;
This seems to fix my problems. I hope it doesn't cause any others.
It might be that the entire problem can be fixed by setting lenwritten
to 0 in the try_output routine (lines 261-266). I dunno.
Thanks for a great product!
--Bjoren Davis
More information about the cvsnt-dev
mailing list