clean-up code before throwing an exception may also throw | | |
Hello, in my program I have a function (pseudo code):
void start_mysql_service()
{
obtain handle
start mysql service using handle
if start fails close handle and throw an exception containing error
description
else just close handle and return
}
So no matter if the service is successfully started or not, the handle needs
to be closed to prevent leakage. But the function that closes the handle may
also throw. How should I handle that? catch the close-handle-exception in
start_mysql_service()? Right now I don't catch anything in the
start_mysql_service() function so if it fails to start the service it
prepares to throw an exception, that exception never gets thrown if it the
close handle functions throws. I don't want one error hiding another one.
The real code looks like this and it's ugly (and contains some platform
specific material, sorry about that):
void
start_mysql_service()
{
/* May throw an exception. */
SC_HANDLE mysql_service = get_mysql_service_handle();
if(!StartService(mysql_service, 0, NULL))
{
/* May throw an exception and if it does I never get to throw */
/* the exception indicating that StartService() failed. */
close_service_handle(mysql_service);
/* TODO: Obtain more precise cause of error if possible using
GetLastError() and FormatMessage(). */
throw runtime_error("StartService() failed.");
}
/* May throw an exception. */
close_service_handle(mysql_service);
}
Any ideas how to restructure this into nicer-looking code and solving the
problem of one error hiding another one?
/ E | | | | re: clean-up code before throwing an exception may also throw
Eric Lilja wrote:[color=blue]
> Hello, in my program I have a function (pseudo code):
>
> void start_mysql_service()
> {
> obtain handle
>
> start mysql service using handle
>
> if start fails close handle and throw an exception containing error
> description
>
> else just close handle and return
> }
>[/color]
[color=blue]
> So no matter if the service is successfully started or not, the handle needs
> to be closed to prevent leakage. But the function that closes the handle may
> also throw. How should I handle that? catch the close-handle-exception in
> start_mysql_service()? Right now I don't catch anything in the
> start_mysql_service() function so if it fails to start the service it
> prepares to throw an exception, that exception never gets thrown if it the
> close handle functions throws. I don't want one error hiding another one.
> The real code looks like this and it's ugly (and contains some platform
> specific material, sorry about that):[/color]
Use nested try catch blocks
[color=blue]
> void
> start_mysql_service()
> {
> /* May throw an exception. */
> SC_HANDLE mysql_service = get_mysql_service_handle();
>
> if(!StartService(mysql_service, 0, NULL))
> {
> /* May throw an exception and if it does I never get to throw */
> /* the exception indicating that StartService() failed. */[/color]
try
{[color=blue]
> close_service_handle(mysql_service);[/color]
}
catch (...)
{
// we don't care about this exception, we want
// to say what that StartService failed, so we
// catch and ignore it.
}[color=blue]
>[/color]
// note: this TODO should probably go before the call to
// call to close_service_handle(), so that any error in c_s_h()
// doesn't mask the results from StartService()[color=blue]
> /* TODO: Obtain more precise cause of error if possible using
> GetLastError() and FormatMessage(). */
> throw runtime_error("StartService() failed.");
> }
>
> /* May throw an exception. */
> close_service_handle(mysql_service);
> }
>
>
> Any ideas how to restructure this into nicer-looking code and solving the
> problem of one error hiding another one?
>
> / E
>
>[/color] | | | | re: clean-up code before throwing an exception may also throw
"Eric Lilja" <ericliljaNoSpam@yahoo.com> skrev i en meddelelse
news:crhska$82b$1@news.island.liu.se...[color=blue]
> Hello, in my program I have a function (pseudo code):
>
> void start_mysql_service()
> {
> obtain handle
>
> start mysql service using handle
>
> if start fails close handle and throw an exception containing error
> description
>
> else just close handle and return
> }[/color]
First off, the handle should be wrapped into a class providing RAII.
Now your code is reduced into this simpler:
class raii_handle
{
public:
//constructor: obtains handle
//destructor: releases handle
};
void start_mysql_service()
{
handle_class hc(); // constructor allocates
start mysql service using handle
}
[color=blue]
>
> So no matter if the service is successfully started or not, the handle
> needs to be closed to prevent leakage. But the function that closes the
> handle may also throw. How should I handle that? catch the
> close-handle-exception in start_mysql_service()? Right now I don't catch
> anything in the[/color]
I do not see why the closing the handle could trigger an exception:
releasing a ressource ought to always be safe. But assuming your statement
is true and the close can't be ignored, i would augment the handle-class to
have a close method:
class raii_handle
{
public:
//constructor: obtains handle
//destructor: releases handle
~raii_handle()
{
try
{
close();
}
catch (...)
{
// either assert or log error - or just plainly ignore it.
// in places where the errorcheck is needed, you can do an
// explicit close
}
}
void close(); // could throw
};
/Peter | | | | re: clean-up code before throwing an exception may also throw
"Peter Koch Larsen" <pklspam@mailme.dk> wrote in message
news:F4%Cd.80603$Vf.3685593@news000.worldonline.dk ...[color=blue]
>
> "Eric Lilja" <ericliljaNoSpam@yahoo.com> skrev i en meddelelse
> news:crhska$82b$1@news.island.liu.se...[color=green]
>> Hello, in my program I have a function (pseudo code):
>>
>> void start_mysql_service()
>> {
>> obtain handle
>>
>> start mysql service using handle
>>
>> if start fails close handle and throw an exception containing error
>> description
>>
>> else just close handle and return
>> }[/color]
>
> First off, the handle should be wrapped into a class providing RAII.
>
> Now your code is reduced into this simpler:
>
> class raii_handle
> {
> public:
> //constructor: obtains handle
> //destructor: releases handle
> };
>
> void start_mysql_service()
> {
> handle_class hc(); // constructor allocates[/color]
You mean handle_class hc; I presume. The above declares a function as you
know, a silly typo I've made myself numerous times.
[color=blue]
>
> start mysql service using handle
> }
>
>[color=green]
>>
>> So no matter if the service is successfully started or not, the handle
>> needs to be closed to prevent leakage. But the function that closes the
>> handle may also throw. How should I handle that? catch the
>> close-handle-exception in start_mysql_service()? Right now I don't catch
>> anything in the[/color]
>
> I do not see why the closing the handle could trigger an exception:
> releasing a ressource ought to always be safe. But assuming your statement
> is true and the close can't be ignored, i would augment the handle-class
> to have a close method:
>[/color]
Well, it can fail at least and I (the programmer) want to be notified of
such errors so I'm making close_service_handle() throw. I like the idea of
wrapping the handle in a class..it gets more robust because you cannot
forget to close the handle, the destructor will do it for you. But if the
destructor fails to close the handle I want to know somehow..an exception is
not a good idea I guess..I like the logging idea you proposed.
[color=blue]
>
> class raii_handle
> {
> public:
> //constructor: obtains handle
> //destructor: releases handle
> ~raii_handle()
> {
> try
> {
> close();
> }
> catch (...)
> {
> // either assert or log error - or just plainly ignore it.
> // in places where the errorcheck is needed, you can do an //
> explicit close
> }
> }
> void close(); // could throw
> };
>
> /Peter
>[/color]
Thanks for your help
/ Eric | | | | re: clean-up code before throwing an exception may also throw
"Eric Lilja" <ericliljaNoSpam@yahoo.com> skrev i en meddelelse
news:crhv7a$8ol$1@news.island.liu.se...[color=blue]
>
> "Peter Koch Larsen" <pklspam@mailme.dk> wrote in message
> news:F4%Cd.80603$Vf.3685593@news000.worldonline.dk ...[color=green]
>>
>> "Eric Lilja" <ericliljaNoSpam@yahoo.com> skrev i en meddelelse
>> news:crhska$82b$1@news.island.liu.se...[/color][/color]
[snip]
[color=blue][color=green]
>> Now your code is reduced into this simpler:
>>
>> class raii_handle
>> {
>> public:
>> //constructor: obtains handle
>> //destructor: releases handle
>> };
>>
>> void start_mysql_service()
>> {
>> handle_class hc(); // constructor allocates[/color]
>
> You mean handle_class hc; I presume. The above declares a function as you
> know, a silly typo I've made myself numerous times.[/color]
Of course.[color=blue]
>[/color]
[snip]
[color=blue][color=green]
>>
>> I do not see why the closing the handle could trigger an exception:
>> releasing a ressource ought to always be safe. But assuming your
>> statement is true and the close can't be ignored, i would augment the
>> handle-class to have a close method:
>>[/color]
>
> Well, it can fail at least and I (the programmer) want to be notified of
> such errors so I'm making close_service_handle() throw. I like the idea of[color=green]
> > wrapping the handle in a class..it gets more robust because you cannot[/color]
> forget to close the handle, the destructor will do it for you. But if the
> destructor fails to close the handle I want to know somehow..an exception
> is not a good idea I guess..I like the logging idea you proposed.
>[/color]
Right. But do examine WHY the call might fail. I've never seen errors of a
type that couldn't either be ignored or replaced by an assertion.
[snip] |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,510 network members.
|