Skip to content

Commit 85aa5f1

Browse files
author
Matevz Morato
committed
Cherry-pick read&write timeouts
2 parents 1c13960 + 15ed081 commit 85aa5f1

File tree

6 files changed

+135
-8
lines changed

6 files changed

+135
-8
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ The following environment variables can be set to alter default behavior of the
197197
| DEPTHAI_SEARCH_TIMEOUT | Specifies timeout in milliseconds for device searching in blocking functions. |
198198
| DEPTHAI_CONNECT_TIMEOUT | Specifies timeout in milliseconds for establishing a connection to a given device. |
199199
| DEPTHAI_BOOTUP_TIMEOUT | Specifies timeout in milliseconds for waiting the device to boot after sending the binary. |
200+
| DEPTHAI_RPC_READ_TIMEOUT | Specifies timeout in milliseconds for reading RPC responses. If 0, wait indefinitely. |
201+
| DEPTHAI_RPC_WRITE_TIMEOUT | Specifies timeout in milliseconds for writing RPC requests. If 0, wait indefinitely. |
200202
| DEPTHAI_PROTOCOL | Restricts default search to the specified protocol. Options: any, usb, tcpip. |
201203
| DEPTHAI_DEVICE_MXID_LIST | Restricts default search to the specified MXIDs. Accepts comma separated list of MXIDs. Lists filter results in an "AND" manner and not "OR" |
202204
| DEPTHAI_DEVICE_ID_LIST | Alias to MXID list. Lists filter results in an "AND" manner and not "OR" |

cmake/Depthai/DepthaiDeviceSideConfig.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set(DEPTHAI_DEVICE_SIDE_MATURITY "snapshot")
33

44
# "full commit hash of device side binary"
5-
set(DEPTHAI_DEVICE_SIDE_COMMIT "b5224fbf5cceeb810a2e1abf27a4387cb817ea26")
5+
set(DEPTHAI_DEVICE_SIDE_COMMIT "dce3b2b64b47f27d91d37ada301ee4ed3a00ef83")
66

77
# "version if applicable"
88
set(DEPTHAI_DEVICE_SIDE_VERSION "")

examples/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,4 +432,8 @@ target_compile_definitions(cast_diff PRIVATE BLOB_PATH="${diff_model}")
432432
dai_add_example(spatial_tiny_yolo_tof_v3 SpatialDetection/spatial_tiny_yolo_tof.cpp OFF OFF)
433433
dai_add_example(spatial_tiny_yolo_tof_v4 SpatialDetection/spatial_tiny_yolo_tof.cpp OFF OFF)
434434
target_compile_definitions(spatial_tiny_yolo_tof_v3 PRIVATE BLOB_PATH="${tiny_yolo_v3_blob}")
435-
target_compile_definitions(spatial_tiny_yolo_tof_v4 PRIVATE BLOB_PATH="${tiny_yolo_v4_blob}")
435+
target_compile_definitions(spatial_tiny_yolo_tof_v4 PRIVATE BLOB_PATH="${tiny_yolo_v4_blob}")
436+
437+
# Misc
438+
## Crash dump
439+
dai_add_example(crash_dump Misc/CrashDump/crash_dump.cpp OFF OFF)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <iostream>
2+
3+
#include "depthai/depthai.hpp"
4+
5+
// Main intention of this example is to test and verify the crash dump functionality works as intended
6+
int main() try {
7+
std::cout << "This example crashes the device on pressing 'c' key. Press 'q' to quit." << std::endl;
8+
// Create pipeline
9+
dai::Pipeline pipeline;
10+
11+
// Define source and output
12+
auto camRgb = pipeline.create<dai::node::ColorCamera>();
13+
auto xoutVideo = pipeline.create<dai::node::XLinkOut>();
14+
15+
xoutVideo->setStreamName("video");
16+
17+
// Properties
18+
camRgb->setBoardSocket(dai::CameraBoardSocket::CAM_A);
19+
camRgb->setResolution(dai::ColorCameraProperties::SensorResolution::THE_1080_P);
20+
camRgb->setVideoSize(1920, 1080);
21+
22+
xoutVideo->input.setBlocking(false);
23+
xoutVideo->input.setQueueSize(1);
24+
25+
// Linking
26+
camRgb->video.link(xoutVideo->input);
27+
28+
// Connect to device and start pipeline
29+
dai::Device device(pipeline);
30+
31+
auto video = device.getOutputQueue("video");
32+
33+
while(true) {
34+
auto videoIn = video->get<dai::ImgFrame>();
35+
36+
// Get BGR frame from NV12 encoded video frame to show with opencv
37+
// Visualizing the frame on slower hosts might have overhead
38+
cv::imshow("video", videoIn->getCvFrame());
39+
40+
int key = cv::waitKey(1);
41+
if(key == 'q' || key == 'Q') {
42+
return 0;
43+
}
44+
if(key == 'c') {
45+
device.crashDevice();
46+
}
47+
}
48+
return 0;
49+
} catch(const std::exception& ex) {
50+
std::cerr << "Error: " << ex.what() << std::endl;
51+
return 1;
52+
}

include/depthai/device/DeviceBase.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,12 @@ class DeviceBase {
906906
*/
907907
bool isClosed() const;
908908

909+
/**
910+
* Crashes the device
911+
* @warning ONLY FOR TESTING PURPOSES, it causes an unrecoverable crash on the device
912+
*/
913+
void crashDevice();
914+
909915
/**
910916
* Returns underlying XLinkConnection
911917
*/

src/device/DeviceBase.cpp

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include "depthai/device/DeviceBase.hpp"
22

33
// std
4+
#include <chrono>
45
#include <iostream>
6+
#include <stdexcept>
57

68
// shared
79
#include "depthai-bootloader-shared/Bootloader.hpp"
@@ -49,7 +51,8 @@ const std::string MAGIC_FACTORY_FLASHING_VALUE = "413424129";
4951
const std::string MAGIC_FACTORY_PROTECTED_FLASHING_VALUE = "868632271";
5052

5153
const unsigned int DEFAULT_CRASHDUMP_TIMEOUT = 9000;
52-
const unsigned int RPC_READ_TIMEOUT = 30000;
54+
const unsigned int DEFAULT_RPC_READ_TIMEOUT = 10000;
55+
const unsigned int DEFAULT_RPC_WRITE_TIMEOUT = 0; // 0 means blocking
5356

5457
// local static function
5558
static void getFlashingPermissions(bool& factoryPermissions, bool& protectedPermissions) {
@@ -534,13 +537,44 @@ unsigned int getCrashdumpTimeout(XLinkProtocol_t protocol) {
534537
return DEFAULT_CRASHDUMP_TIMEOUT + (protocol == X_LINK_TCP_IP ? device::XLINK_TCP_WATCHDOG_TIMEOUT.count() : device::XLINK_USB_WATCHDOG_TIMEOUT.count());
535538
}
536539

540+
unsigned int getRPCReadTimeout() {
541+
std::string timeoutStr = utility::getEnv("DEPTHAI_RPC_READ_TIMEOUT");
542+
if(!timeoutStr.empty()) {
543+
try {
544+
return std::stoi(timeoutStr);
545+
} catch(const std::invalid_argument& e) {
546+
logger::warn("DEPTHAI_RPC_READ_TIMEOUT value invalid: {}", e.what());
547+
}
548+
}
549+
return DEFAULT_RPC_READ_TIMEOUT;
550+
}
551+
552+
unsigned int getRPCWriteTimeout() {
553+
std::string timeoutStr = utility::getEnv("DEPTHAI_RPC_WRITE_TIMEOUT");
554+
if(!timeoutStr.empty()) {
555+
try {
556+
return std::stoi(timeoutStr);
557+
} catch(const std::invalid_argument& e) {
558+
logger::warn("DEPTHAI_RPC_WRITE_TIMEOUT value invalid: {}", e.what());
559+
}
560+
}
561+
return DEFAULT_RPC_WRITE_TIMEOUT;
562+
}
563+
564+
tl::optional<std::string> saveCrashDump(dai::CrashDump& dump, std::string mxId) {
565+
std::vector<uint8_t> data;
566+
utility::serialize<SerializationType::JSON>(dump, data);
567+
auto crashDumpPathStr = utility::getEnv("DEPTHAI_CRASHDUMP");
568+
return saveFileToTemporaryDirectory(data, mxId + "-depthai_crash_dump.json", crashDumpPathStr);
569+
}
570+
537571
void DeviceBase::closeImpl() {
538572
using namespace std::chrono;
539573
auto t1 = steady_clock::now();
540574
auto timeout = getCrashdumpTimeout(deviceInfo.protocol);
541575
bool shouldGetCrashDump = false;
542576
if(!dumpOnly && timeout > 0) {
543-
pimpl->logger.debug("Device about to be closed...");
577+
pimpl->logger.debug("Crash dump collection enabled - first try to extract an existing crash dump");
544578
try {
545579
if(hasCrashDump()) {
546580
connection->setRebootOnDestruction(true);
@@ -556,8 +590,10 @@ void DeviceBase::closeImpl() {
556590
pimpl->logger.debug("shutdown call error: {}", ex.what());
557591
shouldGetCrashDump = true;
558592
}
593+
} else {
594+
pimpl->logger.debug("Crash dump collection disabled - skipping existing crash dump extraction");
559595
}
560-
596+
pimpl->logger.debug("Device about to be closed...");
561597
// Close connection first; causes Xlink internal calls to unblock semaphore waits and
562598
// return error codes, which then allows queues to unblock
563599
// always manage ownership because other threads (e.g. watchdog) are running and need to
@@ -616,6 +652,8 @@ void DeviceBase::closeImpl() {
616652
}
617653
} else if(shouldGetCrashDump) {
618654
pimpl->logger.warn("Device crashed. Crash dump retrieval disabled.");
655+
} else if(timeout == 0) {
656+
pimpl->logger.debug("Crash dump collection disabled, skip device reconnection");
619657
}
620658

621659
pimpl->logger.debug("Device closed, {}", duration_cast<milliseconds>(steady_clock::now() - t1).count());
@@ -827,11 +865,23 @@ void DeviceBase::init2(Config cfg, const dai::Path& pathToMvcmd, tl::optional<co
827865

828866
try {
829867
// Send request to device
830-
rpcStream->write(std::move(request));
831-
868+
auto writeTimeout = getRPCWriteTimeout();
869+
if(writeTimeout > 0) {
870+
auto success = rpcStream->write(std::move(request), std::chrono::milliseconds(writeTimeout));
871+
if(!success) {
872+
throw std::runtime_error("RPC write timed out in " + std::to_string(writeTimeout) + "ms");
873+
}
874+
} else {
875+
rpcStream->write(std::move(request));
876+
}
832877
// Receive response back
833878
// Send to nanorpc to parse
834-
return rpcStream->read(std::chrono::milliseconds(RPC_READ_TIMEOUT));
879+
auto timeout = getRPCReadTimeout();
880+
if(timeout > 0) {
881+
return rpcStream->read(std::chrono::milliseconds(timeout));
882+
} else {
883+
return rpcStream->read();
884+
}
835885
} catch(const std::exception& e) {
836886
// If any exception is thrown, log it and rethrow
837887
pimpl->logger.debug("RPC error: {}", e.what());
@@ -1123,6 +1173,19 @@ std::string DeviceBase::getConnectedIMU() {
11231173
return pimpl->rpcClient->call("getConnectedIMU").as<std::string>();
11241174
}
11251175

1176+
void DeviceBase::crashDevice() {
1177+
// Check that the protective ENV variable is set
1178+
if(utility::getEnv("DEPTHAI_CRASH_DEVICE") != "1") {
1179+
pimpl->logger.error("Crashing the device is disabled. Set DEPTHAI_CRASH_DEVICE=1 to enable.");
1180+
return;
1181+
}
1182+
try {
1183+
pimpl->rpcClient->call("crashDevice");
1184+
} catch(const std::system_error& ex) {
1185+
pimpl->logger.debug("Crash device threw an exception: {} (expected)", ex.what());
1186+
}
1187+
}
1188+
11261189
dai::Version DeviceBase::getIMUFirmwareVersion() {
11271190
std::string versionStr = pimpl->rpcClient->call("getIMUFirmwareVersion").as<std::string>();
11281191
try {

0 commit comments

Comments
 (0)