Connecting Tech Pros Worldwide Forums | Help | Site Map

clean-up code before throwing an exception may also throw

Eric Lilja
Guest
 
Posts: n/a
#1: Jul 23 '05
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



red floyd
Guest
 
Posts: n/a
#2: Jul 23 '05

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]

Peter Koch Larsen
Guest
 
Posts: n/a
#3: Jul 23 '05

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


Eric Lilja
Guest
 
Posts: n/a
#4: Jul 23 '05

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


Peter Koch Larsen
Guest
 
Posts: n/a
#5: Jul 23 '05

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]


Closed Thread