An interesting error...



  • Base exception: System.Net.Sockets.SocketException: The operation completed successfully

     This just got thrown by one of our asp.net apps. 

     



  • Also known as:  System.Runtime.InteropServices.ForgotToGetLastWin32ErrorException (The operation probably did not complete successfully, but we aren't really sure)



  • @Aaron said:

    Also known as:  System.Runtime.InteropServices.ForgotToGetLastWin32ErrorException (The operation probably did not complete successfully, but we aren't really sure)

    Thats about as informative as the first first error.


  • @galgorah said:

    Thats about as informative as the first first error.

    About as useful, yes, about as informative... well it got me thinking about Win32 and realizing it's likely that old issue where you end up with the outcome of a function used in the cleanup as your error rather than the call that crashed.

    Not sure if you missed the extra detail or thought it was blatantly obvious, but it didn't tick over in my head at the first error that that was what's going on. Might've eventually occured to me, but I probably haven't done enough low-level Win32 API work to recognize that error for what it is that easily (though from a protecting my sanity perspective I think I've done more than enough)...



  • @galgorah said:

    Thats about as informative as the first first error.
     

    To a user, yes.  To a programmer, assuming you can get a stack trace, it actually does tell you what you need to look for (a GetLastWin32Error that happens several statements after the API call, or a SocketException created with the parameterless constructor, probably several lines into a "finally" block).

    Not that it really matters, seeing as how it isn't a real exception type.  I was just pointing out what it meant, and what pretty much every other "Error: Success" message means.



  • They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.



  • @RiX0R said:

    They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.

    Except it doesn't make sense because the Win32 error code 0 really means "The operation completed successfully".



  • @Spectre said:

    @RiX0R said:
    They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.

    Except it doesn't make sense because the Win32 error code 0 really means "The operation completed successfully".

    They should change the error message to "The operation completed successfully, or completed with an error but didn't set the last-error code, or completed with an error and did set the last-error code but something else cleared it before it was later retrieved, or possibly something else happened."

     



  • @DaveK said:

    @Spectre said:

    @RiX0R said:
    They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.

    Except it doesn't make sense because the Win32 error code 0 really means "The operation completed successfully".

    They should change the error message to "The operation completed successfully, or completed with an error but didn't set the last-error code, or completed with an error and did set the last-error code but something else cleared it before it was later retrieved, or possibly something else happened."

    Window's error is fine, .NET's accidental loss of the error info then reporting the success of another call that's wrong. Perhaps .NET's exception should say "We accidentally threw away the detailed error description that could've helped you... something's broken..." :P



  • I think they should change the error message for code 0 to "Your retarded".

    Then people will come here and complain about the punctuation.

    And we can tell them it's short for "Your retarded behavior produced this worthless error message because you're too stupid to program".

    Then we all get to have a good laugh at they're expense.



  • @fyjham said:

    @DaveK said:

    @Spectre said:

    @RiX0R said:
    They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.

    Except it doesn't make sense because the Win32 error code 0 really means "The operation completed successfully".

    They should change the error message to "The operation completed successfully, or completed with an error but didn't set the last-error code, or completed with an error and did set the last-error code but something else cleared it before it was later retrieved, or possibly something else happened."

    Window's error is fine, .NET's accidental loss of the error info then reporting the success of another call that's wrong. Perhaps .NET's exception should say "We accidentally threw away the detailed error description that could've helped you... something's broken..." :P

    Err... perhaps .NET's exception should say "An incompetent programmer designed an application where, when a Win32 API call returns FALSE (indicating an error), we just throw an exception - and pray that the last error code won't get stomped on during one of the handlers or other compiler/runtime infrastructure that has to be invoked in between then and the time we finally reach the landing pad however many levels up the stack we've had to unwind, so that the final exception handler can call GetLastError then and hope to retrieve the error code set by the function call just before we threw the exception".  There's no two ways about it, the value of GetLastError is highly volatile and transient and the only correct practice is to capture it immediately after the function call that errors.  You can then place it into a DWORD-sized field in your exception object and throw it back up the stack, and it will be possible to accurately report the correct message no matter what has to happen in between throw and catch.  This has nothing to do with exceptions, it's just the same kind of dumb coding error as

      if (write (fd, buf, size) < 0)
    {
        fprintf (stderr, "Whoops! There was an error\n");
        fprintf (stderr, "And the errno was %d\n", errno);
    }

     

     



  • @DaveK said:

    Err... perhaps .NET's exception should say "An incompetent programmer designed an application where, when a Win32 API call returns FALSE (indicating an error), we just throw an exception - and pray that the last error code won't get stomped on during one of the handlers or other compiler/runtime infrastructure that has to be invoked in between then and the time we finally reach the landing pad however many levels up the stack we've had to unwind, so that the final exception handler can call GetLastError then and hope to retrieve the error code set by the function call just before we threw the exception".  There's no two ways about it, the value of GetLastError is highly volatile and transient and the only correct practice is to capture it immediately after the function call that errors.  You can then place it into a DWORD-sized field in your exception object and throw it back up the stack, and it will be possible to accurately report the correct message no matter what has to happen in between throw and catch.  This has nothing to do with exceptions, it's just the same kind of dumb coding error as

      if (write (fd, buf, size) < 0)
    {
        fprintf (stderr, "Whoops! There was an error\n");
        fprintf (stderr, "And the errno was %d\n", errno);
    }

     


    Which is a set of behaviour I think sort of describes accidentally throwing away the detailed error description (By calling another function that overrides it) - At least I hope it wasn't intentional =P

    My point was that .NET is the thing making the mistake, not the Windows API, so it's not windows's message that's wrong (It's dead right, it's just not about what the coder wanted to know) but .NET's exception message that's wrong and really should be handled more gracefully than "Error: Success" (But I guess if you predicted it happening you probably wouldn't get the error :P).

    I agree with you about the most likely cause, I'd wonder though whether it's actually getting "stomped on" by the calling code rather than something up the stack but short of reading through the .NET framework (Which I'm not quite curious enough for) I'll take your word for it.



  • @fyjham said:

    My point was that .NET is the thing making the mistake, not the Windows API, so it's not windows's message that's wrong (It's dead right, it's just not about what the coder wanted to know) but .NET's exception message that's wrong and really should be handled more gracefully than "Error: Success" (But I guess if you predicted it happening you probably wouldn't get the error :P).

    I agree with you about the most likely cause, I'd wonder though whether it's actually getting "stomped on" by the calling code rather than something up the stack but short of reading through the .NET framework (Which I'm not quite curious enough for) I'll take your word for it.

    Well, without more info from galgorah, such as a stack trace, we just cannot know whether it's the .NET framework making the mistake, or some user code in the app.  It could be this exception is thrown as-is from somewhere deep down in the .NET stack, or it could be that there's some bogoid error-handling code (do NET exceptions automatically record the GetLastError value on construction?  If they worked that way, then catching and re-throwing an exception might lose the error code) at the user level. 



  • @DaveK said:

    Well, without more info from galgorah, such as a stack trace, we just cannot know whether it's the .NET framework making the mistake, or some user code in the app.  It could be this exception is thrown as-is from somewhere deep down in the .NET stack, or it could be that there's some bogoid error-handling code (do NET exceptions automatically record the GetLastError value on construction?  If they worked that way, then catching and re-throwing an exception might lose the error code) at the user level. 

    The constructor for a .NET Win32Exception (Which SocketException and basically anything based on a Win32 error code inherits from) either requires a Win32 error code or automatically calls to get the last error during it's constructor. Unless the user code is actually creating a new instance of the exception manually (Which would be a real WTF) then the .NET libraries had to put it there.\

    I mean, you see a lot of people do "catch (SocketException ex) { throw ex;}" (Which blows away the stack trace) rather than "catch (SocketException ex) { throw;}", but I've never seen anyone do "catch (SocketException ex) { throw new SocketException();}"... that's what it'd take to get this from user code I think, and that'd just be scary...



  • @fyjham said:

    @DaveK said:

    Well, without more info from galgorah, such as a stack trace, we just cannot know whether it's the .NET framework making the mistake, or some user code in the app.  It could be this exception is thrown as-is from somewhere deep down in the .NET stack, or it could be that there's some bogoid error-handling code (do NET exceptions automatically record the GetLastError value on construction?  If they worked that way, then catching and re-throwing an exception might lose the error code) at the user level. 

    The constructor for a .NET Win32Exception (Which SocketException and basically anything based on a Win32 error code inherits from) either requires a Win32 error code or automatically calls to get the last error during it's constructor. Unless the user code is actually creating a new instance of the exception manually (Which would be a real WTF) then the .NET libraries had to put it there.\

    I mean, you see a lot of people do "catch (SocketException ex) { throw ex;}" (Which blows away the stack trace) rather than "catch (SocketException ex) { throw;}", but I've never seen anyone do "catch (SocketException ex) { throw new SocketException();}"... that's what it'd take to get this from user code I think, and that'd just be scary...

    Well, doesn't that mean our options are either that that happened, or that it was in fact the underlying win32 api call that trampled on the last error code before .NET had a chance to construct the exception?  Actually I guess the other possibility is that the .NET source code says "throw new SocketExcepton (0)", or called some other syscalls after the failing call and before constructing the exception but I don't see we can be sure which layer is at fault from the outside.

    And this is TDWTF, after all.  Why shouldn't there be scary user code involved? 



  • Yeah, you're right, there is multiple possibilities that it could be. I was assuming the SocketException was coming from .NET's connection libraries and that .NET's code was blowing away the error value with it's cleanup code before throwing the exception - I guess that might not be the case though, cause the constructor for a SocketException isn't internal so anyone can produce one... I'd just really hope nobody would actually create one themselves because anything that might create one really should be going through the classes that'd create it for you if it's relevant anyway :P



  • @Spectre said:

    @RiX0R said:
    They should change the error message for code 0 to:

    "The error code was cleared before it was retrieved by the application"

    It's way more descriptive and would cut down stupid screenshots in error'd by half.

    Except it doesn't make sense because the Win32 error code 0 really means "The operation completed successfully".

    Yeah, but you're never going to ACTUALLY try to look at the error code unless something didn't. Unless you're an idiot.



  • @DaveK said:

    This has nothing to do with exceptions, it's just the same kind of dumb coding error as

    if (write (fd, buf, size) < 0)
    {
        fprintf (stderr, "Whoops! There was an error\n");
        fprintf (stderr, "And the errno was %d\n", errno);
    }

    Except that won't even do that, not exactly:

    The value of errno is zero at program startup, but is never set to zero by any library function.84 The value of errno may be set to nonzero by a library function call whether or not there is an error, provided the use of errno is not documented in the description of the function in the Standard.

    84. Thus, a program that uses errno for error checking should set it to zero before a library function call, then inspect it before a subsequent library function call.

    Important bit hilighted - while there are other issues (namely, the printf may cause errno to be set to some other error condition that it was in fact able to recover from), it won't actually zero it out - no standard function does that.


Log in to reply