Re: Denial of denial of service

[prev] [thread] [next] [lurker] [Date index for 2007/01/29]

From: Sean Conner
Subject: Re: Denial of denial of service
Date: 00:39 on 29 Jan 2007
It was thus said that the Great Yossi Kreinin once stated:
> 
> The problem is that a lot of calling code *doesn't* bother to check the 
> status. People don't like to do that, especially when they can't abort 
> right there and must propagate status up the call chain, so they deny the 
> existence of errors. And sometimes they don't even know there's an "exit 
> status" (because of not being fully aware of errno, herrno and the like). 
> And sometimes they clobber the status (with things like sqrt(-1) + 
>  sqrt(4)).

  Error handling is difficult, and it isn't taught very well in shools. 
True story:  I was writing a program (a BBS game for a friend that ran a
BBS) and fell into the following trap:  I detect an error, like the
configuration file doesn't exist.  I can't print the error to the screen,
since most likely, my friend won't *see* it (once the program ends, the BBS
takes over, and overwrites the screen).  Okay, so I'll log it to a file, but
what if the disk fills up?  This is a pretty bad error.  Okay, in *that*
case, I should log it to the printer, but what if the printer is turned off
or otherwise unavailable?  What then?

  As I was in school at the time, I approached one of the instructors [1]
with this conumdrum and his answer to me:  if you don't know how to handle
an error, then don't bother checking for the error.

  Flash forward a couple of years.  I'm doing an internship at IBM, and the
code I'm working on was nothing but function calls wrapped in IF statements:

	if ((rc = SomeReallyObscureAPICall(a,monsterously,long,parameter,list,with
		&some,&references,like,&this)) != OKAY)
	{
	  return(SOME_OTHER_ERROR);
	}

	if ((rc = SomeOtherAPICall(again,with,a,monsterous,&parameter,
		list)) != OKAY)
	{
	  if (rc == SOME_TYPE_OF_ERROR)
	    return (SOME_OBSCURE_ERROR);
	  else
	    return (OTHERWISE_WE_EXPECT_THIS);
	}

	if ((rc = YetAnotherAPICallWithALongName(but,unlike,the,other,
		calls,&has,a,shorter,parameter,list)) != OKAY)
	{
	  cleanup(has,reference,&parameter);
	  return(A_CRAP_ANOTHER_BUGUS_RETURN_CODE);
	}

which to me, obscured what the function was attempting to do, lost in the
forest for all the IF trees.  After working at IBM, I came to call such code
"middle management code" since it really does nothing but pass work down the
line, and pass the buck back up.

  A few years ago, I wrote a bunch of code that actually maintained an error
stack, and you would do stuff like:

	rc = SomeOtherAPICall(&the,real,return,data,in,the,first,parameter);
	if (rc != OKAY)
	{
	  return ErrorPush(MODULE_NAME,MODULE_LOCATION,ERROR_SOME_ERROR,
		"i(this is an int) i(another int) $(string)",
		"%a and %b to SomeOtherAPICall() returned %c");
	}

  where the error would be pushed into an error stack, and it was presumed,
that SomeOtherAPICall() would have done the same, all the way down.  So you
get a stack of errors that bubbled up.  I usually ended up either clearing
the error stack (because the error, was indeed, expected in the normal
processing---say, and end of file) or just logging the entire stack to a log
file.  

  A few years go by, and the whole aparatus I wrote was just too cumbersom
to use on any regular basis, keeping track of the module names (really, an
enumeration of the module) and error codes (having to assign ranges, keep
some open, blah blah) and having to include the monsterous call to
ErrorPush() was just ... distracting from what I was trying to accomplish.

  Now, I try to avoid returning errors as much as possible, but I'm
beginning to like the Erland approach to errors:  just crash and let some
other monitoring program restart the errent program.

> I don't like throw/catch in C++ because it slows down the entire body of 
> code and because you *don't* get a call stack (so even abort() with a core 
> dump is better than throw) and because I don't like anything in C++. But in 
> a managed environment, I think I like exceptions, unless it's a huge bulk 
> of code with very hairy failure modes, in which case I don't know.

  I don't like throw/catch because it's a form of GOTO, only the target of
the GOTO isn't implicitely specified (it's more of a COMEFROM than a GOTO,
and even then, where you are implicitely coming from isn't stated).  

  Besides, aren't exceptions really meant for ... well ... exception
conditions that normally should never arise, like division by 0, or writing
to NULL?  I could even seen semi-exceptional conditions like end of file
where you aren't expecting an end of file, but for *everything*?

  Blah.

> Exceptions and error codes aside, people who trap SIGSEGV should be shot.

  Oh, come on now ... how else do you expect us to reattempt the operation
using a different algorithm?

  -spc (Has caught SIGSEGV, but only when I would otherwise not get a core
	dump and needed to know where the problem was---easy enough to catch
	SIGSEGV and log the information I needed)

[1]	He wasn't a full professor, but had worked at IBM for a bazillion
	years before retiring.  Once he retired from IBM, he bacame an
	instructor at Florida Atlantic University, just across the street
	from IBM Boca.

There's stuff above here

Generated at 23:01 on 06 Feb 2007 by mariachi 0.52