From 5f410ef051252d9961065c5441051c2395cc84eb Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 27 Mar 2007 19:10:10 +0000 Subject: [PATCH] In the wake of r7415, let's have some better error reporting. Instead of passing -1 to its gotdata and sentdata callbacks on error, winhandl.c will now pass the negation of the Windows error number; and the Plink front end will now format that into an error message and pass it on to the user. [originally from svn r7416] [r7415 == 702a92ceb848394f722292cd4a54c414d4e0be67] --- windows/winhandl.c | 59 +++++++++++++++++++++++++++++----------------- windows/winplink.c | 18 +++++++++++--- 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/windows/winhandl.c b/windows/winhandl.c index 9f120dc0..f300962c 100644 --- a/windows/winhandl.c +++ b/windows/winhandl.c @@ -96,7 +96,7 @@ struct handle_input { */ char buffer[4096]; /* the data read from the handle */ DWORD len; /* how much data that was */ - int readret; /* lets us know about read errors */ + int readerr; /* lets us know about read errors */ /* * Callback function called by this module when data arrives on @@ -113,7 +113,7 @@ static DWORD WINAPI handle_input_threadfunc(void *param) struct handle_input *ctx = (struct handle_input *) param; OVERLAPPED ovl, *povl; HANDLE oev; - int readlen; + int readret, readlen; if (ctx->flags & HANDLE_FLAG_OVERLAPPED) { povl = &ovl; @@ -132,16 +132,21 @@ static DWORD WINAPI handle_input_threadfunc(void *param) memset(povl, 0, sizeof(OVERLAPPED)); povl->hEvent = oev; } - ctx->readret = ReadFile(ctx->h, ctx->buffer, readlen, - &ctx->len, povl); - if (!ctx->readret) - error = GetLastError(); - if (povl && !ctx->readret && error == ERROR_IO_PENDING) { + readret = ReadFile(ctx->h, ctx->buffer,readlen, &ctx->len, povl); + if (!readret) + ctx->readerr = GetLastError(); + else + ctx->readerr = 0; + if (povl && !readret && ctx->readerr == ERROR_IO_PENDING) { WaitForSingleObject(povl->hEvent, INFINITE); - ctx->readret = GetOverlappedResult(ctx->h, povl, &ctx->len, FALSE); + readret = GetOverlappedResult(ctx->h, povl, &ctx->len, FALSE); + if (!readret) + ctx->readerr = GetLastError(); + else + ctx->readerr = 0; } - if (!ctx->readret) { + if (!readret) { /* * Windows apparently sends ERROR_BROKEN_PIPE when a * pipe we're reading from is closed normally from the @@ -149,12 +154,12 @@ static DWORD WINAPI handle_input_threadfunc(void *param) * isn't a natural EOF, _nothing_ is. So if we get that * particular error, we pretend it's EOF. */ - if (error == ERROR_BROKEN_PIPE) - ctx->readret = 1; + if (ctx->readerr == ERROR_BROKEN_PIPE) + ctx->readerr = 0; ctx->len = 0; } - if (ctx->readret && ctx->len == 0 && + if (readret && ctx->len == 0 && (ctx->flags & HANDLE_FLAG_IGNOREEOF)) continue; @@ -239,7 +244,7 @@ struct handle_output { * and read by the main thread after receiving that signal. */ DWORD lenwritten; /* how much data we actually wrote */ - int writeret; /* return value from WriteFile */ + int writeerr; /* return value from WriteFile */ /* * Data only ever read or written by the main thread. @@ -257,6 +262,7 @@ static DWORD WINAPI handle_output_threadfunc(void *param) { struct handle_output *ctx = (struct handle_output *) param; OVERLAPPED ovl, *povl; + int writeret; if (ctx->flags & HANDLE_FLAG_OVERLAPPED) povl = &ovl; @@ -271,14 +277,23 @@ static DWORD WINAPI handle_output_threadfunc(void *param) } if (povl) memset(povl, 0, sizeof(OVERLAPPED)); - ctx->writeret = WriteFile(ctx->h, ctx->buffer, ctx->len, - &ctx->lenwritten, povl); - if (povl && !ctx->writeret && GetLastError() == ERROR_IO_PENDING) - ctx->writeret = GetOverlappedResult(ctx->h, povl, - &ctx->lenwritten, TRUE); + writeret = WriteFile(ctx->h, ctx->buffer, ctx->len, + &ctx->lenwritten, povl); + if (!writeret) + ctx->writeerr = GetLastError(); + else + ctx->writeerr = 0; + if (povl && !writeret && GetLastError() == ERROR_IO_PENDING) { + writeret = GetOverlappedResult(ctx->h, povl, + &ctx->lenwritten, TRUE); + if (!writeret) + ctx->writeerr = GetLastError(); + else + ctx->writeerr = 0; + } SetEvent(ctx->ev_to_main); - if (!ctx->writeret) + if (!writeret) break; } @@ -524,7 +539,7 @@ void handle_got_event(HANDLE event) /* * EOF, or (nearly equivalently) read error. */ - h->u.i.gotdata(h, NULL, (h->u.i.readret ? 0 : -1)); + h->u.i.gotdata(h, NULL, -h->u.i.readerr); h->u.i.defunct = TRUE; } else { backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len); @@ -538,13 +553,13 @@ void handle_got_event(HANDLE event) * write. Call the callback to indicate that the output * buffer size has decreased, or to indicate an error. */ - if (!h->u.o.writeret) { + if (h->u.o.writeerr) { /* * Write error. Send a negative value to the callback, * and mark the thread as defunct (because the output * thread is terminating by now). */ - h->u.o.sentdata(h, -1); + h->u.o.sentdata(h, -h->u.o.writeerr); h->u.o.defunct = TRUE; } else { bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten); diff --git a/windows/winplink.c b/windows/winplink.c index 0819934c..42426000 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -228,7 +228,13 @@ int stdin_gotdata(struct handle *h, void *data, int len) /* * Special case: report read error. */ - fprintf(stderr, "Unable to read from standard input\n"); + char buf[4096]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, -len, 0, + buf, lenof(buf), NULL); + buf[lenof(buf)-1] = '\0'; + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + fprintf(stderr, "Unable to read from standard input: %s\n", buf); cleanup_exit(0); } noise_ultralight(len); @@ -249,8 +255,14 @@ void stdouterr_sent(struct handle *h, int new_backlog) /* * Special case: report write error. */ - fprintf(stderr, "Unable to write to standard %s\n", - (h == stdout_handle ? "output" : "error")); + char buf[4096]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, -new_backlog, 0, + buf, lenof(buf), NULL); + buf[lenof(buf)-1] = '\0'; + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + fprintf(stderr, "Unable to write to standard %s: %s\n", + (h == stdout_handle ? "output" : "error"), buf); cleanup_exit(0); } if (connopen && back->connected(backhandle)) {