> wrote in message news:xxxxx@ntdev…
>>
>> Some years ago, we had to do DNS name resolution on program startup, so
>> it
>> could re-establish communication. There were no asynchronous DNS calls
>> then, so I did it all in a backround thread, with an unobtrusive
>> progress
>> bar displayed on the status bar. An attempt to shut the program down
>> required putting up a dialog that said “waiting for network response”
>> and
>> I later added a progress bar that counted down 70 seconds (and recorded
>> the time right before the call so it was mostly accurate). That thread
>> could not be broken out of the gethostbyname (if I’ve remembered the
>> call
>> correctly) function even by a call to ExitThread.
>>
>
> In our example we are dealing with a problem. A problem that is caused by
> a
> synchronous API that is blocking for way too long. I consider it just an
> easy way out to put it in the face of the end user by means of a waiting
> dialog so that now it becomes HIS problem instead. Like Windows Live Mail,
> it sucks. Like fighting over sand, it doesn’t mean you should, just
> because
> you can. And if the end user is savvy enough he will almost certainly kill
> off the hanging app with the task manager. That is worse than terminating
> the process in a controlled manner.
>
> In the above example, when it’s time to say goodbye for a process I don’t
> put up a dialog box telling the user he should quietly wait. What I do is,
> set a flag in my program so that
>> notify soneone the thread has cleanly terminated
> is no longer required and will be ignored if it happens thereafer
> regardless. So terminating the entire process at this point after the
> necessary cleanup has been done, is the only right thing to do in my
> book.
> The kernel will clean up all outstanding resources that I do not care
> about.
> Call that erroneous and if you still do consider that there are
> synchronous
> API calls that can block for much longer than 70 seconds.
>
> If you want to carve a rule in stone that says “TerminateThread is evil
> and
> should never be used” you can count me in. TerminateThread can leave your
> program in an undefined state and will leak. It’s not even allowed to use
> as
> a last recourse when the program exists because it can potentially
> deadlock.
>
> If you want to carve a rule in stone that says “TerminateProcess is evil
> and
> should never be used” then I say hold on a second.
>
Actually, it is extremely evil. Consider the following (very real) case
(which I had to fix)
The subroutine library was written by people who had no concept of
robustness. If they found, for example, an error in the database index
file (this was a library that allowed direct access to dBase IV
databases), they just called exit(-1). When I asked why, they said “if
the index is messed up, we can’t continue”. Fine. But we were working
with an app that did realtime data collection while processing report
creation in a separate thread. So we had the main GUI thread, the data
collection thread, and the report-printing thread. When they called
exit(-1), the process terminated, losing irreplaceable data. All I wanted
to do was shut down the report thread if there was an error in the
indexing. Since this was for a liquid CO2 chromatograph, it could be used
in contexts such as forensic analysis. I was called in because it had
actually crashed, losing valuable and non-reproducible evidence (by the
way, CO2 CAN be a liquid, at 10,000psi). I did not write the program, but
fortunately they had purchased the library in source form. Fixing it was
a real trial because there was no error-propagation path (why bother, when
you’re going to exit?) so it was not easy to change hundreds of little
subroutines from void to DWORD (actually, ERROR_TYPE, which was typedefed
to DWORD) so the error was propagated back.
Far too many programmers were taught, either by their professor or books,
that the proper response to a serious error is to exit the program. So
when we were using dbx (the Berkely predecessor of gdb), any time it got
uncomfortable, it exited. One of our staff found there were several
hundred exit() calls in it, and he meticulously replaced each one with
code that would simply return an error. Before he did this, it was simply
unusable.
So yes, ExitProcess is evil, and should never be used. Because most
(perhaps all) instances I have seen of its use were actually incorrect,
resulting in programs that simply disappeared in a puff of greasy blue
smoke. Have you ever been on the wrong side of a tech support call from
an important customer, trying to find out what happened? “It just
disappeared. No dialog box, no debug output, just gone” and then try to
reproduce it? I have been, and it was not a comfortable place to be. I
solved the problem by finding all the exit() calls and telling the
responsible programmer that he had a week to replace every one of them
with a sane recovery mechanism, and exiting the program was not a
permissible option. The feedback after product release was “This release
is so much better! It no longer crashes!” (Lots of users had the
problem, and attributed it to poor quality control and poor testing; only
one of them called, and the VP sales called me to take the call, because
all the tech support people had gone to lunch).
It is every bit as evil as ExitThread.
> My opinion is that kernel programming should be treated as an exact
> science
> in which we have to be pragmatic, correct, unequivocal and 100% loyal to
> our
> principles. Because if we don’t everybody knows the consequences.
>
> Programming in ring 3 in my book can be considered a craftsmanship at
> least
> in part because it offers us the luxury to weigh in various factors other
> than sterile academic correctness such as reasonability, user experience
> and
> the human factor.
Human factors are critical. The program does not own the right to exit in
case of an error (I’m talking primarily about GUI programs here); that
right is granted solely to the user.
I first hit this when Pascal was still a new toy. The problem was that
the programmer had used some function that read a number from the console,
but if you typed an ill-formed number (such as “1…23”, “cat”, or “1r6”
[note r and e are adjacent keys on the U.S. keyboard layout, and perhaps
others), the read-number routine just exited the program, instead of
returning an error code so the message "Your number ‘1r6’ is not a valid
number, please re-enter it). He had written a program to help teachers
enter grades, so if they had 50 students in the class and made an error
typing a number for the 50th student, the program exited, bang, and the
poor user had to start over). So I showed how to write code that parsed a
number (using an FSM) and issued the error message for ill-formed numbers.
Yes, this was in the Bad Old Days of Teletype input, prompt-and-read
paradigm, which made it that much worse). Note that _ttoi() will return 0
for all those examples, which is equallly unacceptable.
>
> //Daniel
>
>
> “Now some of us build and some of us teach,
> some of us build and some of us teach.
> And some of us kill what some of us eat.
> That is a fact of life.”
>
I teach how to build. How to build buildings that won’t fall down, that
have restrooms on every floor, and water fountains, and other nice
features (we used to live in an apartment building with an architect, and
I learned a lot listening to him…such as don’t put the food service
counter in a location that causes a line to form that blocks access to the
doors, or the restrooms). The hardest problem to teach newly-minted
programmers is that “it works” is not sufficient. Third-order effects can
kill you.
I once had a debate in which one programmer said, of his device driver,
“if I see something seriously wrong, I just call BugCheck()” and thought
not only did that make sense, but defended his choice. So I said,
“Suppose you had a guest at your house. He uses the bathroom, and finds
you are out of toilet paper and don’t have a fresh roll in arm’s reach.
So his response is to burn down your house. Right. Your driver is a
guest in the operating system, and is not entitled to burn the house down
for trivial problems. And all problems must be considered trivial from
the viewpoint of the operating system”.
joe
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>