Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Destructor throwing exception 'std::system_error' what(): Unknown error 16777216. Should sensor be closed and stopped? #10420

Closed
sison54 opened this issue Apr 19, 2022 · 17 comments

Comments

@sison54
Copy link

sison54 commented Apr 19, 2022

Required Info
Camera Model L515
Firmware Version (Open RealSense Viewer --> Click info)
Operating System & Version Ubuntu Mate 20.04
Kernel Version (Linux Only) 5.4.0-1058-raspi
Platform Raspberry Pi
SDK Version 2.5.0
Language C++
Segment ???

Issue Description

It seems that a destructor of some sort is throwing an exception that is terminating my application. It is not all the time and is very inconsistent, but I can get it to do it at least every few hours.

Here is the exception that I am getting when my application terminates:

throwing exception terminate called after throwing an instance of 'std::system_error'   what():  Unknown error 16777216

The exception is not able to be caught in a try catch block as it seems to happen after certain objects are going out of scope. It's possible I may be doing something wrong here so I just wanted to see if there was a bug somewhere, a known issue, or user error on my part. I believe I may have fixed the problem, but I am not sure if this is correct.

In my examples I tried to narrow it down to the simplest thing. I am calling this function every 10 seconds in a loop just for testing this error.

Here is the code that fails, the exception never gets caught, but when the function scope ends, an exception is thrown and the application is terminated:

float GetDepthScale ()
{
    try
    {
        rs2::pipeline pipe {};
        const auto profile = pipe.start ();
        const auto sensor = profile.get_device ().first<rs2::depth_sensor> ();
        const auto scale = sensor.get_depth_scale ();

        pipe.stop ();

        return scale;
    }
    catch (const std::exception& exc)
    {
        std::cout << "GetDepthScale ERROR:"  << exc.what () << std::endl;
        return 0;
    }
    catch (...)
    {
        std::cout << "GetDepthScale ERROR:" << std::endl;
        return 0;
    }
}

Here is how I seemed to fix it, I created an object that has rs2::pipeline _pipe {} as a member variable, and I make sure to stop and close the sensor:

class RealSenseL515
{
public:
    float GetDepthScale ();
private:
    rs2::pipeline _pipe {};
};

float RealSenseL515::GetDepthScale ()
{
    try
    {
        const auto profile = _pipe.start ();
        const auto sensor = profile.get_device ().first<rs2::depth_sensor> ();
        const auto scale = sensor.get_depth_scale ();

        sensor.stop ();
        sensor.close ();

        _pipe.stop ();

        return scale;
    }
    catch (const std::exception& exc)
    {
        std::cout << "GetDepthScale ERROR:"  << exc.what () << std::endl;
        return 0;
    }
    catch (...)
    {
        std::cout << "GetDepthScale ERROR:" << std::endl;
        return 0;
    }
}

I have only been running with this solution for a few hours with no errors so far, but I am not 100% confident on the solution. What is the recommended way of closing and stopping the sensor, doing it manually, or letting it do it in the destructor? What about with the pipe, should it be stopped manually, or can the destructor do it?

Thanks!

@sison54
Copy link
Author

sison54 commented Apr 19, 2022

UPDATE: Even with the second version above I still get the exception.

@MartyG-RealSense
Copy link
Collaborator

MartyG-RealSense commented Apr 20, 2022

Hi @sison54 If a function that has a block of code nested inside it is defined so that the function can be called by name elsewhere in the script to activate the nested code block, its opening line is typically defined as void () - for example, void FunctionName() - but I note that your script uses float() to define the function name.

A small number of RealSense users who experienced errors when performing start and then stop found that the problem was resolved if they did pipe.start() and sensor.stop() instead of pipe.start() and pipe.stop()

Also, if the problem was related to retrieving the depth scale value in real-time rather than caused by repeated start-stop then you could simply set the depth scale variable to the fixed numeric value of the L515's depth scale instead of retrieving it with an instruction. The L515's default depth scale is 0.000250 and this value does not change unless deliberately done so by a program instruction.

@sison54
Copy link
Author

sison54 commented Apr 20, 2022

Thanks for your reply,
I am not sure what you mean by your first statement exactly.

I will try doing pipe start and sensor stop to see if that solves the problem.

It has nothing to do with the depth scale specifically. I just broke the problem down to the simplest case just to demonstrate the problem and to make it easier to debug. The same problem also happens in other similar functions where I am starting and stopping but I am getting frames, and setting options, etc. Th get depths scale is the simplest of the cases and the issue occurs.

@MartyG-RealSense
Copy link
Collaborator

What I meant is that I have not previously seen functions that start with float instead of void. For example, this function definition in one of the RealSense SDK's C++ example programs:

https://github.com/IntelRealSense/librealsense/blob/master/examples/align-advanced/rs-align-advanced.cpp#L140

@sison54
Copy link
Author

sison54 commented Apr 20, 2022

I am sorry for the confusion here, but what about this function, the one right above that you gave an example of:

https://github.com/IntelRealSense/librealsense/blob/master/examples/align-advanced/rs-align-advanced.cpp#L126

@MartyG-RealSense
Copy link
Collaborator

The align-advanced script is not important to this discussion. I am just using it to illustrate that in my experience, a function usually starts with 'void' instead of 'float'. For example: void GetDepthScale () {

@sison54
Copy link
Author

sison54 commented Apr 20, 2022

I updated my code example to include my object that contains a pipe and I returned 0 in cases where an exception is caught. Again, exceptions are never caught even though one is thrown. This is an indication that the throw happens in a destructor.

I think the return value in this case is irrelevant as I don't think this has anything to do with the error. The point here is that some destructor in the library is throwing an exception, which crashes the application and gives no way to recover.

@MartyG-RealSense
Copy link
Collaborator

The SDK's error handling documentation provides a note about destructors.

https://dev.intelrealsense.com/docs/librealsense-error-handling-scheme


Note Regarding Destructors: The only case when an exception will be handled internally without notifying the user, is as part of object destruction flow. For example, when the device object is being destroyed we might get system call failures due to the device being disconnected. Any such errors will be documented in the log but not risen to the user to avoid throw-in-destructor problems.


My research could only find one past case though on this support forum at #7553 that discusses a potential destructor related error.

@sison54
Copy link
Author

sison54 commented Apr 20, 2022

I will try doing pipe start and sensor stop to see if that solves the problem.

I tried this, and got the same error.

Whats expected workflow? Are pipes supposed to able to be started/stopped?

Note Regarding Destructors: The only case when an exception will be handled internally without notifying the user, is as part of object destruction flow. For example, when the device object is being destroyed we might get system call failures due to the device being disconnected. Any such errors will be documented in the log but not risen to the user to avoid throw-in-destructor problems.

This doesnt seem to be the case since I am getting throw-in-destructor problems.

@MartyG-RealSense
Copy link
Collaborator

Yes, you can start and stop pipes. A circumstance where an error can occur is if stop is called when a pipe is not currently active (as you cannot call stop before start).

@sison54
Copy link
Author

sison54 commented Apr 20, 2022

Here is the core dump stack trace:

#0  __libc_do_syscall () at ../sysdeps/unix/sysv/linux/arm/libc-do-syscall.S:47
#1  0xb4cc985e in __libc_signal_restore_set (set=0xbeb8232c) at ../sysdeps/unix/sysv/linux/internal-signals.h:86
#2  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3  0xb4cba332 in __GI_abort () at abort.c:79
#4  0xb4eb3370 in ?? () from /lib/arm-linux-gnueabihf/libstdc++.so.6
#5  0xb4eb2866 in ?? () from /lib/arm-linux-gnueabihf/libstdc++.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

@MartyG-RealSense
Copy link
Collaborator

There have been past cases on the 400 Series cameras where a piece of the computer's memory was consumed each time that a start-stop was performed (i.e a 'memory leak' that degrades performance as memory is consumed over time until the program becomes unstable or exits). #8091 is a C++ example of such a case.

So it may be worth monitoring memory during the test-running of your application to see whether similar progressive memory consumption is occurring with the L515.

@sison54
Copy link
Author

sison54 commented Apr 25, 2022

I don't think its a memory issues. I did not see any memory usage that climb over time. Also it crashes at random, sometimes it takes 15 minutes sometime sit takes hours. I have a feeling its some sort of compatibility issue with my environment, although I have no evidence to prove that. For the moment I am just going to leave the pipe open. I ran for several days without stopping the pipe and saw no issues. This application will be running 24/7, so if I see any issues I will re evaluate.

@MartyG-RealSense
Copy link
Collaborator

Okay, thanks very much @sison54 for the update. Let's keep this case open for a further time period to give you the opportunity to perform more long-run testing. Thanks again and good luck!

@MartyG-RealSense
Copy link
Collaborator

Hi @sison54 Do you have an update about this case that you can provide, please? Thanks!

@sison54
Copy link
Author

sison54 commented May 6, 2022

I have no further update. Although I never found the root cause, leaving the pipe open is able to solve my problem as a workaround. As long as this doesn't cause any hardware issues in the long run this should be ok, until some reason a rises that I have to start and stop the pipe again.

@MartyG-RealSense
Copy link
Collaborator

Thanks very much @sison54 for the update! As your workaround is acting as a solution for now, I will close the case. Please feel free to re-open it or start a new case at a future date if you need to because a problem occurs again. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants