clean-up code before throwing an exception may also throw

E

Eric Lilja

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
 
R

red floyd

Eric said:
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):

Use nested try catch blocks
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. */ try
{
close_service_handle(mysql_service);
}
catch (...)
{
// we don't care about this exception, we want
// to say what that StartService failed, so we
// catch and ignore it.
}// 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()
 
P

Peter Koch Larsen

Eric Lilja said:
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
}

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
}

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

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
 
E

Eric Lilja

Peter Koch Larsen said:
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

You mean handle_class hc; I presume. The above declares a function as you
know, a silly typo I've made myself numerous times.
start mysql service using handle
}



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:

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.
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

Thanks for your help

/ Eric
 
P

Peter Koch Larsen

Eric Lilja said:
Peter Koch Larsen said:
"Eric Lilja" <[email protected]> skrev i en meddelelse
news:[email protected]...

[snip]
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

You mean handle_class hc; I presume. The above declares a function as you
know, a silly typo I've made myself numerous times.

Of course.
[snip]
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:

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.

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]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,217
Latest member
topweb3twitterchannels

Latest Threads

Top