can we clear errono after function call - c++

I have some function call like below, and want to print success after success call, but got failure, even the function actually behave correctly.
int myfunction() {
// does some linux sys call for example
int error = run_cmd ("ifconfig usb10 up");
int syserrorno = errno;
strerror(syserrorno);
return error;
}
int main(){
int error =1;
int retry = 0;
do {
error = myfunction();
retry++;
}
while ( error !=-1 && retry <3);
return 0;
}
Basically I tried to:
Run a syscal via myFunction, return error = 1 if fail or 0 if success.
The return error in myFunction is the same as in syscal.
The syscal is a posix spawn command that I reuse from library.
If there is error, print error, redo 3 times.
So I have 1st run of syscall unsuccessfully; it returns error and print out "unavailabe resources". It is expected.
The second time is successful as I check the usb10 and it is up. But it still prints out the same error instead of success.
Is there a way to print it correctly ?

When using errno, always set errno=0; before calling the function(s) whose status you want to check. C library and POSIX functions will set errno to a non-zero value if they encounter an error, but they do not reset it to zero if they succeed.
(The reason they work this way: When a function reporting via errno is actually implemented in terms of other functions, you don't want a later success to make errno forget about an earlier failure. This also makes it possible for user code to set errno=0;, call a number of closely-related library functions, and just check for overall success or failure after all of those calls.)

Related

How to get the exit code of a Boost process?

I wondering, how to get the exit code of my child process. The function exit_code() always return 0, doesn't matter terminated (send SIGKILL) or correctly finished.
I am using boost ver 1.65 and C++0x. I cant change these settings.
As I read in the documentation:
int exit_code() const;
Get the exit_code. The return value is without any meaning if the child wasn't waited for or if it was terminated.
So this function is not helping me, but I may could use the error code.
std::error_code ec;
bp::system("g++ main.cpp", ec);
But std::error_code is only supported since c++11. I tried boost::system::error_code, but thats not correct.
Here the link to Boost::process:
https://www.boost.org/doc/libs/1_65_0/doc/html/boost_process/tutorial.html
Any idea, how to get that exit code?
You should be able to get the exit code simply by checking the return value:
int ec = bp::system("g++ main.cpp");
The overload taking an std::error_code is only for handling the edge case of g++ not existing in the first place (so it can never start the executable, and therefore there is no exit code). If you do not use that function, it will throw an exception on failure instead.1
try {
int ec = bp::system("g++ main.cpp");
// Do something with ec
} catch (bp::process_error& exception) {
// g++ doesn't exist at all
}
A cleaner way to do this would be to resolve g++ yourself first by searching the $PATH environment variable (just like your shell would):
auto binary_path = bp::search_path(`g++`);
if (binary_path.empty()) {
// g++ doesn't exist
} else {
int ec = bp::system(binary_path, "main.cpp");
}
1 Note, however, that C++0x is C++11, just before it was formally standardized, and that it is very likely your standard library will support std::error_code even if you tell it to use C++0x.

How do I design error codes in c++?

I am writing a c-style function:
enum {
EFUNC1,
EFUNC2,
}
int func0() {
int err = 0;
if((err=func1())!=0) {
// return err or return EFUNC1
}
if((err=func2())!=0) {
// return err or return EFUNC2
}
return 0;
}
func1 and func2 are c functions and they have their own error codes. What should I do when func1 or func2 return an error? I figure out some ways:
Design my error codes. The number of error codes is the sum of func1's and func2's. When the call stack is deep, the number of error codes becomes large.
Simply return the result of func1 or func2. There is no way to know which function fails since their error codes may overlap.
Design my error codes and the number of the codes is equal to the number of functions. The caller just know which function return error, but he don't know the further reason.
Throw an exception wrapping the failed function name and its error code.
What's the best practice?
The previous code example is ambiguous. I modified it.
Why expose the complexity of func0() to the caller? Usually the caller is not interested in what happens in the body of the function, he just wants the job to be done.
func0() should notify the user on why it failed to complete its goal (to terminate without errors). They are many ways to do that. One example could be this:
// On success: Return 0
// On error: Return -1
int func0() {
if(func1() == -1) {
printf("Error in func0: func1 returned error code -1");
return -1;
}
if(func2() == -2) {
printf("Error in func0: func1 returned error code -2");
return -1;
}
return 0;
}
Note that here we don't allow func2() to be executed if func1() fails, since that might be dangerous.
For instance, if func1() is suppose to allocate space for an array that func2() is going to use, then let's say that func1() fails (because malloc() failed). func2() should not be called, since func1() failed in that case, because the array that func2() expects to be ready for use, is not available at runtime.
Echoing tobi303's comment, the logic behind error codes is as follows:
If a routine (func0) will fail when an error occurs in a certain subroutine (func1), the routine should stop immediately on error and report back to the caller.
To do otherwise makes no sense. For example, if func0 is to make coffee, func1 is to get some beans and func2 is to brew, then without the beans, you are just brewing air. Telling someone you can't brew air isn't awfully helpful.
If a routine can gracefully handle an error in its subroutine, then its not an error at all for the caller of the routine. In this case, no error should be returned.
So the structure of your program for the first case should be simply
int func0()
{
if(int err = func1())
return err;
if(int err = func2())
return err;
return 0;
}
And the second case
int func0()
{
if(int err = func1())
handle(err);
if(int err = func2())
return err;
return 0;
}

What am I missing about boost::mpi::request ? Testing seems to change state

So I've got this simple MPI example thrown together. I'm seeing some weird behavior around testing boost::mpi::request that I can't explain. Specifically, if you remove the commenting on the second loop, it spins forever. Does test on a boost::mpi::request only return true once? If so, what bit of state is getting updated? I've poked through Boost's MPI and optional code and I can't explain what I'm seeing.
(naturally, for the uninitiated, you'll need to use mpiexec with two nodes to run this yourself.)
# include "stdafx.h"
# include <boost/serialization/string.hpp>
# include <boost/mpi.hpp>
# include <windows.h>
# include <iostream>
# include <boost/mpi.hpp>
# include <boost/optional.hpp>
int main(int argc, char *argv[]);
int main(int argc, char *argv[])
{
boost::mpi::environment m_env;
boost::mpi::communicator m_world;
if (m_world.rank() == 0)
{
m_world.send(1,0, std::string("hi!"));
}
else
{
std::shared_ptr<std::string> rcv = std::shared_ptr<std::string>(new std::string());
boost::mpi::request x = m_world.irecv(0, 0, *rcv);
while (!x.test())
{
Sleep(10);
}
//while (!x.test())
//{
// Sleep(10);
//}
std::cout << *rcv;
}
}
The answer is in the documentation, sort of:
/**
* Determine whether the communication associated with this request
* has completed successfully. If so, returns the #c status object
* describing the communication. Otherwise, returns an empty #c
* optional<> to indicate that the communication has not completed
* yet. Note that once #c test() returns a #c status object, the
* request has completed and #c wait() should not be called.
*/
optional<status> test();
Then look at the docs for the underlying MPI_Test function:
A call to MPI_TEST returns flag = true if the operation identified by request is complete. In such a case, the status object is set to contain information on the completed operation; if the communication object was created by a nonblocking send or receive, then it is deallocated and the request handle is set to MPI_REQUEST_NULL.
One is allowed to call MPI_TEST with a null or inactive request argument. In such a case the operation returns with flag = true and empty status.
So what we see is that Boost MPI's test() method returns an optional<status>, and MPI_Test() can only return a status once (after that, the request is destroyed). MPI_Test() called repeatedly would return flag = true, but that's not what you're checking. If you really need this pattern, you could probably call MPI_Test() yourself and use the returned flag instead of status. Or just do the bookkeeping in your application, and don't call boost::mpi::request::test() twice on the same request.
Another way to look at this problem is that you are using the result of test() in a boolean context, where you expect it to work like the flag of MPI_Test(), but actually it works like the status, and its bool nature is only an illusion.
This is consistent with the MPI standard. When MPI_TEST indicates the operation has completed, the returned status object will contain the information about the completed operation, and the operation object itself is marked inactive or de-allocated (whichever applies). Calling MPI_TEST again on that operation object would return an empty status.
The (latest version of the) MPI standard provides a way to access the status in a non-destructive way : MPI_REQUEST_GET_STATUS.
I'm not aware of an implementation of this operation in boost, but you can just store the returned status object, and refer to that later instead of calling test again.

Why is std::string constructor resetting GetLastError

I'm calling Windows APIs from C++ code and I have a helper method to do the FormatMessage stuff and throw an exception for error handling. The signature of the function is
void throw_system_error(const std::string& msg_prefix, DWORD messageid)
I've noticed something strange. This code does not work properly:
handle = ...;
if (handle == NULL) {
throw_system_error("something bad happened", GetLastError());
}
The error code that is passed to throw_system_error is always zero.
Where as this works just fine:
handle = ...;
if (handle == NULL) {
DWORD error = GetLastError();
throw_system_error("something bad happened", error);
}
Some more investigation showed that this version has the same problem:
handle = ...;
if (handle == NULL) {
std::string msg("something bad happened");
DWORD error = GetLastError();
throw_system_error(msg, error);
}
It looks for all the world as if the constructor of std::string is resetting the error code.
My guess would be that std::string is allocating memory internally which causes some system call that then sets the last error back to zero.
Anyone knows what is actually going on here?
Visual C++ 2015, 64bit.
Let's see the GetLastError documentation:
Most functions that set the thread's last-error code set it when they
fail. However, some functions also set the last-error code when they
succeed.
You should call the GetLastError function immediately when a
function's return value indicates that such a call will return useful
data. That is because some functions call SetLastError with a zero
when they succeed, wiping out the error code set by the most recently
failed function.
So there is one function calling SetLastError, very likely one that allocates memory:
When you construct a string, new is called to allocate memory.
Now, let's see new's implementation in vc++. There is a very good answer to that question in Stack Overflow : https://softwareengineering.stackexchange.com/a/293209
It depends if you are in debug or release mode. In release mode, there is HeapAlloc/HeapFree which are kernel functions,
while in debug mode (with visual studio) there is a hand written
version of free and malloc (to which new/delete are re-directed) with
thread locks and more exceptions detection, so that you can detect
more easily when you did some mistakes with you heap pointers when
running your code in debug mode.
So in release mode, the function called is HeapAlloc, which does NOT call SetLastError. From the documentation:
If the function fails, it does not call SetLastError
So the code should work properly in release mode.
However, in the debug implementation, the function FlsGetValue is called, and that function calls SetLastError when succeeded.
It's very easy to check this,
#include <iostream>
#include <Windows.h>
int main() {
DWORD t = FlsAlloc(nullptr);
SetLastError(23); //Set error to 23
DWORD error1 = GetLastError(); //store error
FlsGetValue(t); //If success, it is going to set error to 0
DWORD error2 = GetLastError(); //store second error code
std::cout << error1 << std::endl;
std::cout << error2 << std::endl;
system("PAUSE");
return 0;
}
It outputs the following:
23
0
So FlsGetValue has called SetLastError(). To prove that it is called only on debug we can do the following test:
#include <iostream>
#include <Windows.h>
int main() {
DWORD t = FlsAlloc(nullptr);
SetLastError(23); //Set error to 23
DWORD error1 = GetLastError(); //store error
int* test = new int; //allocate int
DWORD error2 = GetLastError(); //store second error code
std::cout << error1 << std::endl; //output errors
std::cout << error2 << std::endl;
delete test; //free allocated memory
system("PAUSE");
return 0;
}
If you run it in debug mode, it will give you, because it calls FlsGetValue:
23
0
However, if you run it in release mode, it produces, because it calls HeapAlloc:
23
23
Per the documentation for GetLastError
The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread's last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.
At some point during the construction of std::string, SetLastError is called. The standard library on windows uses Win32 calls as part of its implementation.
Your second method (that works) is the correct way to use GetLastError
You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.
This is normal - the "last error" can be set indirectly through any function call.
Some functions set it to "no error" on success, so if you want to use it reliably you need to store it immediately before you do anything else.
If you've ever encountered an "A serious error occurred: The operation completed successfully" dialogue, this is probably the reason.

how to set expect_call on a function in while loop?

I am using gmock, gtest framework to test a function in my code. And I mocked the function which is called in side the main function which is being tested. The mock function is in a infinite while loop and exits only in case of success and keep prints an error message in case of failure. The mocked function looks like this,
while((fd = (socket(_,_,_)) < 0)
{
print("error")
}
return fd;
now I want to make the socket function fails and prints the error. I managed to print the error but since it's int he while loop it keeps printing the error message. How do I put an expectation so that the gtest stops printing after 1 or 2 times. I put the expectation like this
EXPECT_CALL(object, socket(_,_,_)).WillRepeatedly(return (error));
I tried with putting .Times(2), but it didn't work.
You'll need to have socket return a value >= 0 if you want the while loop to exit:
int error(-1), success(0);
EXPECT_CALL(object, socket(_,_,_))
.WillOnce(Return(error))
.WillOnce(Return(error))
.WillOnce(Return(success));