Segfault when attempting to start stream
When attempting to start a stream (I am trying to stream video from a Logitech C920), the program segfaults.
Code:
let ctx = uvc::Context::new().unwrap();
let dev = ctx.find_device(None, None, None).unwrap();
let handle = dev.open().unwrap();
let format = uvc::StreamFormat {
width: WIDTH,
height: HEIGHT,
fps: FPS,
format: FrameFormat::MJPEG
};
let mut stream_handle = handle.get_stream_handle_with_format(format).unwrap();
let (mjpeg_sender, mut mjpeg_receiver) = watch::channel(Vec::new());
let _stream = stream_handle.start_stream(
|frame, sender| {
let frame_vec = frame.to_bytes().to_vec();
// not sure if safe to panic
let _ = sender.broadcast(frame_vec);
},
mjpeg_sender,
).unwrap();
// use channel at this point
When running it, I get:
unsupported descriptor subtype VS_COLORFORMAT
unsupported descriptor subtype VS_COLORFORMAT
attempt to claim already-claimed interface 1
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Some other program is must be using my camera for some reason, which probably should be causing either a panic or causing a function to return an error, but should probably not be causing a segfault from safe Rust.
If you'd like, I can try and debug this from my machine, and I can try and potentially pull request a fix in.
If you have a backtrace that would be very helpful!
BTW: You are allowed to panic in the stream, the current behaviour is to catch at the FFI behaviour and ignore
@Noah-Kennedy I pushed the latest version to 'crates.io` which should fix a double free if your function should crash mid-stream.
@Noah-Kennedy Have you managed to get somewhere on the debugging?
@mulimoen Have same issue with a different camera (UHM 350)
Ubuntu 18.04 64 bit
$ cargo run --example mirror
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/examples/mirror`
Found device: Bus 001 Device 004 : ID 04f2:3501 UHM350 (Micro )
unsupported descriptor subtype VS_COLORFORMAT
[1] 30303 segmentation fault (core dumped) cargo run --example mirror
Rust doesn't provide the option to expose the stacktrace it seems.
EDIT: obtained stacktrace via debugger
gef➤ r
Starting program: /home/orion/projects/skool/rover/experiments/libuvc-rs/target/debug/examples/mirror
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6550700 (LWP 911)]
Found device: Bus 001 Device 004 : ID 04f2:3501 UHM350 (Micro )
unsupported descriptor subtype VS_COLORFORMAT
[New Thread 0x7ffff5d4f700 (LWP 913)]
Thread 1 "mirror" received signal SIGSEGV, Segmentation fault.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x00005555556250a0 → <<alloc::string::String+0> sub rsp, 0x38
$rcx : 0x0
$rdx : 0x1
$rsp : 0x00007fffffffaba0 → 0x000055555603e9c0 → 0x0000555556030920 → 0x0000555556036490 → 0x000055555603feb0 → 0x000055555603c720 → 0xc000010401ea0209
$rbp : 0x7fffff7ff000
$rsi : 0x0
$rdi : 0x0
$rip : 0x00005555556f206d → <uvc::device::FrameDescriptor::intervals+77> mov ecx, DWORD PTR [rax]
$r8 : 0x0
$r9 : 0x00007ffff5d4f700 → 0x00007ffff5d4f700 → [loop detected]
$r10 : 0x00007ffff5d4f9d0 → 0x0000000000000391
$r11 : 0x202
$r12 : 0x00007fffffffade0 → 0x0000000000000006
$r13 : 0x00007fffffffd9e8 → 0x0000000000000000
$r14 : 0x00007fffffffb318 → 0x000055555601a240 → 0x0000030e02000b08
$r15 : 0x00005555556250a0 → <<alloc::string::String+0> sub rsp, 0x38
$eflags: [zero carry parity adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffaba0│+0x0000: 0x000055555603e9c0 → 0x0000555556030920 → 0x0000555556036490 → 0x000055555603feb0 → 0x000055555603c720 → 0xc000010401ea0209 ← $rsp
0x00007fffffffaba8│+0x0008: 0x000055555603e9c0 → 0x0000555556030920 → 0x0000555556036490 → 0x000055555603feb0 → 0x000055555603c720 → 0xc000010401ea0209
0x00007fffffffabb0│+0x0010: 0x000055555603e9c0 → 0x0000555556030920 → 0x0000555556036490 → 0x000055555603feb0 → 0x000055555603c720 → 0xc000010401ea0209
0x00007fffffffabb8│+0x0018: 0x00005555556f210a → <<uvc::device::FrameDescriptors+0> mov QWORD PTR [rsp+0x18], rax
0x00007fffffffabc0│+0x0020: 0x0000000000000000
0x00007fffffffabc8│+0x0028: 0x0000000000000000
0x00007fffffffabd0│+0x0030: 0x000055555603e9c0 → 0x0000555556030920 → 0x0000555556036490 → 0x000055555603feb0 → 0x000055555603c720 → 0xc000010401ea0209
0x00007fffffffabd8│+0x0038: 0x0000000000000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x5555556f205d <uvc::device::FrameDescriptor::intervals+61> call QWORD PTR [rip+0x90dda5] # 0x555555fffe08
0x5555556f2063 <uvc::device::FrameDescriptor::intervals+67> mov QWORD PTR [rsp+0x20], rax
0x5555556f2068 <uvc::device::FrameDescriptor::intervals+72> mov rax, QWORD PTR [rsp+0x20]
→ 0x5555556f206d <uvc::device::FrameDescriptor::intervals+77> mov ecx, DWORD PTR [rax]
0x5555556f206f <uvc::device::FrameDescriptor::intervals+79> mov DWORD PTR [rsp+0x54], ecx
0x5555556f2073 <uvc::device::FrameDescriptor::intervals+83> cmp ecx, 0x0
0x5555556f2076 <uvc::device::FrameDescriptor::intervals+86> je 0x5555556f2092 <uvc::device::FrameDescriptor::intervals+114>
0x5555556f2078 <uvc::device::FrameDescriptor::intervals+88> mov rax, QWORD PTR [rsp+0x38]
0x5555556f207d <uvc::device::FrameDescriptor::intervals+93> add rax, 0x1
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── source:src/device.rs+406 ────
401 pub fn intervals(&self) -> &[u32] {
402 unsafe {
403 let intervals = (*self.frame_desc.as_ptr()).intervals;
404 let mut len = 0;
405 loop {
// len=0x0, intervals=0x00007fffffffabe8 → 0x0000000000000000
→ 406 let x = *intervals.add(len);
407 if x == 0 {
408 return slice::from_raw_parts::<'a>(intervals, len);
409 }
410 len += 1;
411 }
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "mirror", stopped 0x5555556f206d in uvc::device::FrameDescriptor::intervals (), reason: SIGSEGV
[#1] Id 2, Name: "mirror", stopped 0x7ffff74c8cb9 in __GI___poll (), reason: SIGSEGV
[#2] Id 3, Name: "mirror", stopped 0x7ffff74c8cb9 in __GI___poll (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x5555556f206d → uvc::device::FrameDescriptor::intervals(self=0x7ffffffface8)
[#1] 0x5555555e9525 → uvc::device::DeviceHandle::get_preferred_format(self=0x7fffffffb358, f=mirror::main::closure-0)
[#2] 0x555555652f0c → mirror::main()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x00005555556f206d in uvc::device::FrameDescriptor::intervals (self=0x7ffffffface8) at src/device.rs:406
406 let x = *intervals.add(len);
I'm not familiar with the output from gef, is intervals a pointer with the value 0x00007fffffffabe8 pointing to zero? I don't quite get why that would SEGFAULT
Gef is an extension of GDB geared towards binary analysis.
Its got multiple sections to it,
- State of the registers.
- State of the Stack.
- Disassembly view.
- Code view
- Stop reasons(would need to look this up, im not immediately familiar with this section)
- call stack
- offending line
My x86 assembly is quite weak, but looks like its trying to dereference rax, which is NULL. This naturally should segfault.
→ 0x5555556f206d <uvc::device::FrameDescriptor::intervals+77> mov ecx, DWORD PTR [rax]
$rax : 0x0
Poking the crash a bit, it appears intervals is null going into line 406 of uvc::device::FrameDescriptor::intervals
gef➤ info locals
len = 0x0
intervals = 0x0
I've made a bugfix in #18, please check if this solves your problem
It doesn't segfault now, but it does still panic.
$ RUST_BACKTRACE=full cargo debug -- --example mirror
args: ["/home/orion/.cargo/bin/cargo-debug", "debug", "--", "--example", "mirror"]
Finished dev [unoptimized + debuginfo] target(s) in 0.06s
00:41:48 [INFO] selected binary: "/home/orion/projects/skool/rover/experiments/libuvc-rs/target/debug/examples/mirror"
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
GEF for linux ready, type `gef' to start, `gef config' to configure
75 commands loaded for GDB 8.1.0.20180409-git using Python engine 3.6
[*] 5 commands could not be loaded, run `gef missing` to know why.
Reading symbols from /home/orion/projects/skool/rover/experiments/libuvc-rs/target/debug/examples/mirror...done.
warning: Missing auto-load script at offset 0 in section .debug_gdb_scripts
of file /home/orion/projects/skool/rover/experiments/libuvc-rs/target/debug/examples/mirror.
Use `info auto-load python-scripts [REGEXP]' to list them.
gef➤ r
Starting program: /home/orion/projects/skool/rover/experiments/libuvc-rs/target/debug/examples/mirror
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff6550700 (LWP 14202)]
Found device: Bus 001 Device 004 : ID 04f2:3501 UHM350 (Micro )
unsupported descriptor subtype VS_COLORFORMAT
[New Thread 0x7ffff5d4f700 (LWP 14210)]
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', examples/mirror.rs:70:10
stack backtrace:
0: 0x555555c057f0 - std::backtrace_rs::backtrace::libunwind::trace::h72c2fb8038f1bbee
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/../../backtrace/src/backtrace/libunwind.rs:96
1: 0x555555c057f0 - std::backtrace_rs::backtrace::trace_unsynchronized::h1e3b084883f1e78c
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/../../backtrace/src/backtrace/mod.rs:66
2: 0x555555c057f0 - std::sys_common::backtrace::_print_fmt::h3bf6a7ebf7f0394a
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/sys_common/backtrace.rs:79
3: 0x555555c057f0 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h2e8cb764b7fe02e7
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/sys_common/backtrace.rs:58
4: 0x555555c2716c - core::fmt::write::h7a1184eaee6a8644
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/fmt/mod.rs:1080
5: 0x555555c023c2 - std::io::Write::write_fmt::haeeb374d93a67eac
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/io/mod.rs:1516
6: 0x555555c07bfd - std::sys_common::backtrace::_print::h1d14a7f6ad632dc8
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/sys_common/backtrace.rs:61
7: 0x555555c07bfd - std::sys_common::backtrace::print::h301abac8bb2e3e81
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/sys_common/backtrace.rs:48
8: 0x555555c07bfd - std::panicking::default_hook::{{closure}}::hde0cb80358a6920a
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:208
9: 0x555555c078a8 - std::panicking::default_hook::h9b1a691049a0ec8f
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:227
10: 0x555555c082e1 - std::panicking::rust_panic_with_hook::h2bdec87b60580584
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:577
11: 0x555555c07e89 - std::panicking::begin_panic_handler::{{closure}}::h101ca09d9df5db47
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:484
12: 0x555555c05c5c - std::sys_common::backtrace::__rust_end_short_backtrace::h3bb85654c20113ca
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/sys_common/backtrace.rs:153
13: 0x555555c07e49 - rust_begin_unwind
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
14: 0x555555c25041 - core::panicking::panic_fmt::h48c31e1e3d550146
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85
15: 0x555555c24f8d - core::panicking::panic::h184ede6dd822ffb4
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:50
16: 0x5555556e29aa - core::option::Option<T>::unwrap::h7b750e5dc134384c
at /home/orion/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:383
17: 0x555555652f32 - mirror::main::h305f75d50c5e91d3
at /home/orion/projects/skool/rover/experiments/libuvc-rs/examples/mirror.rs:62
18: 0x55555563225b - core::ops::function::FnOnce::call_once::h46bbd7ce70df7f22
at /home/orion/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227
19: 0x5555555e499e - std::sys_common::backtrace::__rust_begin_short_backtrace::hb9392815093d8720
at /home/orion/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs:137
20: 0x5555556de621 - std::rt::lang_start::{{closure}}::hd5d779ad70c7efb1
at /home/orion/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:66
21: 0x555555c08707 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::he179d32a5d10d957
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:259
22: 0x555555c08707 - std::panicking::try::do_call::hcb3d5e7be089b2b4
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:381
23: 0x555555c08707 - std::panicking::try::h7ac93b0cd56fb701
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:345
24: 0x555555c08707 - std::panic::catch_unwind::h7b40e396c93a4fcd
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panic.rs:382
25: 0x555555c08707 - std::rt::lang_start_internal::h142b9cc66267fea1
at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/rt.rs:51
26: 0x5555556de5f7 - std::rt::lang_start::h85da232f7497e24f
at /home/orion/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/rt.rs:65
27: 0x55555565419a - main
28: 0x7ffff73d5bf7 - __libc_start_main
29: 0x5555555e3d2a - _start
30: 0x0 - <unknown>
[Thread 0x7ffff5d4f700 (LWP 14210) exited]
[Thread 0x7ffff6550700 (LWP 14202) exited]
[Inferior 1 (process 14198) exited with code 0145]
That would suggest there are no formats available for streaming. Does your camera work with other software using uvc?
That would suggest there are no formats available for streaming. Does your camera work with other software using uvc?
Unclear, I haven't tested the camera against uvc itself. AFAIK this camera behaves as a standard USB webcam, which I have been able to read by other means, though i don't think any of those use uvc.
You could call supported_formats to get a list of recognized formats for libuvc. You could also try opening a stream with get_stream_handle_with_format.
using the provided mirror.rs example, modified to make call to devh.supported_formats() doesn't return anything that is immediately meaningful for debugging.
What did appear to work was manually constructing a StreamFormat instance using values I obtained from another image-capture crate eye-rs
let mut streamh = devh.get_stream_handle_with_format(StreamFormat {
width: 1920,
height: 1080,
fps: 30,
format: FrameFormat::MJPEG
}).unwrap();
This produces a bunch of non-fatal errors, but does open the camera and streams live video, so it appears to work. (presumably the errors are the result of this camera not being fully compatable with uvc)
Found device: Bus 001 Device 004 : ID 04f2:3501 UHM350 (Micro )
unsupported descriptor subtype VS_COLORFORMAT
Scanning mode: Err(Pipe)
Auto-exposure mode: Err(Pipe)
Auto-exposure priority: Err(Pipe)
Absolute exposure: Err(Pipe)
Relative exposure: Err(Pipe)
Aboslute focus: Err(Pipe)
Relative focus: Err(Pipe)
attempt to claim already-claimed interface 1
Not a JPEG file: starts with 0x00 0xac
Other
Not all cameras supports all modes and configurations, those errors are somewhat normal. The first frame is also corrupted, I've noticed this before on my own hardware
Thanks for the feedback. I believe the OP's segfault issue is resolved by the patch in #18 .
If i have any further issues they will go in their own tickets. Thanks for the support!