How does __rust_begin_short_backtrace work in Rust? - rust

As titled.
I know that __rust_begin_short_backtrace is used for stack backtracing, but how does it work actually? I find the implementation of it is really short just like below. And what it does is only calling the passed-in function indirectly, and return back the result. I also find the counterpart function __rust_end_short_backtrace which has totally identical implementation. The code is at library/std/src/sys_common/backtrace.rs.
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
/// this is only inline(never) when backtraces in libstd are enabled, otherwise
/// it's fine to optimize away.
#[cfg_attr(feature = "backtrace", inline(never))]
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
where
F: FnOnce() -> T,
{
let result = f();
// prevent this frame from being tail-call optimised away
crate::hint::black_box(());
result
}
Another part of the related implementation is also at "library/std/src/sys_common/backtrace.rs". Below is a snippet of code of this part which I think is highly related and important, but I don't understand the logic here that how Rust deals with the symbols that relate to the previous two functions:
backtrace_rs::trace_unsynchronized(|frame| {
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
return false;
}
let mut hit = false;
let mut stop = false;
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
hit = true;
if print_fmt == PrintFmt::Short {
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
if sym.contains("__rust_begin_short_backtrace") {
stop = true;
return;
}
if sym.contains("__rust_end_short_backtrace") {
start = true;
return;
}
}
}
if start {
res = bt_fmt.frame().symbol(frame, symbol);
}
});
if stop {
return false;
}
if !hit {
if start {
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
}
}
idx += 1;
res.is_ok()
});

Rust is inserting these "dummy symbols" to allow a short backtrace.
Consider this code
fn a() {
b()
}
fn b() {
c()
}
fn c() {
d()
}
fn d() {
panic!()
}
fn main() {
a()
}
This gives a nice backtrace
$ rustc demo.rs
$ RUST_BACKTRACE=1 ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: std::panicking::begin_panic
1: demo::d
2: demo::c
3: demo::b
4: demo::a
5: demo::main
6: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
If we instead use RUST_BACKTRACE=full
$ RUST_BACKTRACE=full ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: 0x107e34fe4 - std::backtrace_rs::backtrace::libunwind::trace::ha70d3c0580051b5e
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
1: 0x107e34fe4 - std::backtrace_rs::backtrace::trace_unsynchronized::h70c3b3ef22cddd13
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x107e34fe4 - std::sys_common::backtrace::_print_fmt::h698e42c1766250fa
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:67:5
3: 0x107e34fe4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h18cc31b07c2f1a67
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:46:22
4: 0x107e4808d - core::fmt::write::h24f8349e8e89c9af
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/fmt/mod.rs:1096:17
5: 0x107e33046 - std::io::Write::write_fmt::hc54d7d6e95b15753
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/io/mod.rs:1568:15
6: 0x107e36b79 - std::sys_common::backtrace::_print::h07ca439149358748
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:49:5
7: 0x107e36b79 - std::sys_common::backtrace::print::hb7331bf9c4b208ca
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:36:9
8: 0x107e36b79 - std::panicking::default_hook::{{closure}}::h11b550d560f5cc66
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:208:50
9: 0x107e36709 - std::panicking::default_hook::he168e99d1cf91c3c
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:225:9
10: 0x107e371fb - std::panicking::rust_panic_with_hook::hf87bfc4afef21ea6
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:591:17
11: 0x107e18d27 - std::panicking::begin_panic::{{closure}}::h631923d2be23e79e
12: 0x107e18998 - std::sys_common::backtrace::__rust_end_short_backtrace::h891b6a0b6f9c1b80
13: 0x107e4bcfb - std::panicking::begin_panic::hd2dfddb0fed650c0
14: 0x107e18aec - demo::d::h9d9ff8ddd5377da5
15: 0x107e18ac9 - demo::c::haceeec3fee4323ba
16: 0x107e18ab9 - demo::b::h4146166847508fc7
17: 0x107e18aa9 - demo::a::h60d47e17615f49c4
18: 0x107e18af9 - demo::main::h60dea0663d4b849d
19: 0x107e18bea - core::ops::function::FnOnce::call_once::hf435db03deecd456
20: 0x107e189cd - std::sys_common::backtrace::__rust_begin_short_backtrace::h936624db758e7870
21: 0x107e194d0 - std::rt::lang_start::{{closure}}::ha060b13a4d59d3f5
22: 0x107e37574 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h0e377e204feaadc3
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:259:13
23: 0x107e37574 - std::panicking::try::do_call::h9c5b8eda90bbe0b7
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:379:40
24: 0x107e37574 - std::panicking::try::he150bdff9d5b30f2
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:343:19
25: 0x107e37574 - std::panic::catch_unwind::h04e9c415c0907892
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:431:14
26: 0x107e37574 - std::rt::lang_start_internal::h86f505dc7de50d93
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/rt.rs:51:25
27: 0x107e194a5 - std::rt::lang_start::h9d080ccd85b4c518
28: 0x107e18b22 - _main
Which is the full stack trace. However is isn't very usefull as most of it is language internals. Therefor, in the normal mode, rust scans the stack for the __rust_end_short_backtrace and __rust_begin_short_backtrace functions.
These functions dont do anything (hence the trickery to stop them being optimized away), but are rust their for the backtracer to pick up.

Related

golang two switch case strange phenomenon

why the second switch code can run when t value not 30, program should return in the first swtich statement, it seems wild.
following is the code:
package main
import (
"fmt"
)
func main() {
fmt.Println("start...")
// change different t value to test
t := 10
switch t {
case 10:
case 20:
case 30:
fmt.Println("30...")
return
default:
fmt.Println("d...")
return
}
fmt.Println("does the following code run ?")
switch t {
case 10:
fmt.Println("10....")
case 20:
fmt.Println("20....")
}
fmt.Println("end...")
}

Print updated value before it should update

Here's a short code
use std::{thread, time::{Duration}, sync::{Arc, Mutex}};
fn main() {
let num = Arc::new(Mutex::new(0u8));
let clone = num.clone();
thread::spawn(move || {
loop {
println!("{:?};", *num.lock().unwrap()); // always prints 0
thread::sleep(Duration::from_secs(1));
*num.lock().unwrap() = 0;
println!("{:?};", *num.lock().unwrap()); // always prints 0
}
});
listen(clone);
}
fn listen(num: Arc<Mutex<u8>>) {
rdev::listen(move |event| {
match event.event_type {
rdev::EventType::KeyPress(_) => {
*num.lock().unwrap() += 1;
},
_ => {},
}
}).unwrap();
}
All it should do is just counting how many times the users pressed any key on a keyboard. But this code is doesn't work.
I added 2 println! statements - before the value is updated and after that. And I assume to get a real value in the first statement and 0 in the second one. But for some reason both println! print a zero.
Why so and how can I avoid it?
The code does work if I don't reset value to a zero. But I have to do it.
It seems that you leave no time between the num read and write. So it writes the num value and immediatly read from it.
You probably want to add an extra delay statement:
loop {
println!("{:?};", *num.lock().unwrap());
thread::sleep(Duration::from_secs(1));
*num.lock().unwrap() = 0;
println!("{:?};", *num.lock().unwrap());
//this delay will allow the other thread to modify the num before the read happens.
thread::sleep(Duration::from_secs(1));
}

How to access as_secs in SystemTime? "no method named `as_secs` found for enum Result" [duplicate]

This question already has answers here:
Unable to read file contents to string - Result does not implement any method in scope named `read_to_string`
(2 answers)
How can I get the current time in milliseconds?
(7 answers)
Closed 2 years ago.
I'm using std::time::SystemTime. My goal is to make a struct with a field called timestamp and store the time in seconds.
I saw this example which works correctly:
use std::time::SystemTime;
match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
When I try this code I get an error:
use std::time::SystemTime;
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
println!("{}", n.as_secs());
error[E0599]: no method named `as_secs` found for enum `std::result::Result<std::time::Duration, std::time::SystemTimeError>` in the current scope
--> src/main.rs:5:22
|
5 | println!("{}", n.as_secs());
| ^^^^^^^ method not found in `std::result::Result<std::time::Duration, std::time::SystemTimeError>`
What am I doing wrong?
Read the error:
no method named `...` found for type `Result<...>`
So, we look at Result:
Result is a type that represents either success (Ok) or faliure (Err)
See the std::result module for documentation details.
So, we know that SystemTime::duration_since(&self, _) returns a Result, meaning it could possibly have failed. Reading the docs:
Returns an Err if earlier is later than self, and the error contains how far from self the time is.
So, we just have to unwrap, expect, or match on it to get the possibility of an error out:
use std::time::SystemTime;
// Unwrapping
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
.unwrap(); // Will panic if it is not `Ok`.
// Expecting
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)
.expect("Invalid time comparison"); // Will panic with error message
// if it is not `Ok`.
// Matching
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
match n {
Ok(x) => { /* Use x */ },
Err(e) => { /* Process Error e */ },
}
// Fallibly Destructuring:
let n = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH);
if let Ok(x) = n {
/* Use x */
} else {
/* There was an error. */
}

Jenkinfile When Condition for env.JOB_NAME

I have a Jenkinsfile I would like to trigger certain steps based on env.JOB_NAME. As a test I have done this;
#!/usr/bin/env groovy
pipeline {
agent any
stages {
stage('Get ID') {
when {
"${env.JOB_NAME}" == 'Notification Sender (dev)'
}
steps {
echo "${env.JOB_NAME}"
}
}
}
}
However I get the error;
WorkflowScript: 6: Expected a when condition # line 6, column 11.
when {
^
WorkflowScript: 6: Empty when closure, remove the property or add some content. # line 6, column 11.
when {
^
Can I make the stage run based on the env.JOB_NAME using the when condition?
Yes, you can.
Try the following
when {
expression {
env.JOB_NAME == 'Notification Sender (dev)'
}
}
There is full documentation on the Pipeline syntax page, but the relevant part is
expression
Execute the stage when the specified Groovy expression evaluates to true, for example: when { expression { return params.DEBUG_BUILD } }

XPages create a full text index in SSJS

I have a DB that must be full text indexed, so I added the code below to create one if it is not allready indexed:
if (database.isFTIndexed()){
database.updateFTIndex(false)
} else {
var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
database.createFTIndex(options , true);
database.updateFTIndex(false);
}
sessionScope.put("ssSelectedView","vwWFSProfile")
When it runs I get the following error:
Error source
Page Name:/xpWFSAdmin.xsp
Control Id: button2
Property: onclick
Exception
Error while executing JavaScript action expression
com.ibm.jscript.types.GeneratedWrapperObject$StaticField incompatible with com.ibm.jscript.types.FBSValue
Expression
1: #{javascript:if (database.isFTIndexed()){
2: database.updateFTIndex(false)
3: } else {
4: var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
5: database.createFTIndex(options , true);
6: database.updateFTIndex(false);
7: }
8: sessionScope.put("ssSelectedView","vwWFSProfile")}
It is choking on line 4 it does not like the summing of the parameters. So I comment out line 4 and change line 5 to read database.createFTIndex(4, true)
then I get this error:
Error while executing JavaScript action expression
Script interpreter error, line=5, col=18: [TypeError] Exception occurred calling method NotesDatabase.createFTIndex(number, boolean) null
JavaScript code
1: if (database.isFTIndexed()){
2: database.updateFTIndex(false)
3: } else {
4: //var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES + database.FTINDEX_IMMEDIATE
5: database.createFTIndex(4 , true);
6: database.updateFTIndex(false);
7: }
8: sessionScope.put("ssSelectedView","vwWFSProfile")
Can't seem to get it to work. I can go into the DB and manually create the index so it is not a rights issue.
As far as I can read from the help, you can not use database.FTINDEX_IMMEDIATE as parameter for createFTIndex() only for setFTIndexFrequency().
So remove the use of database.FTINDEX_IMMEDIATE and do this:
var options:int = database.FTINDEX_ALL_BREAKS + database.FTINDEX_ATTACHED_FILES;
database.createFTIndex(options , true);
You can then call setFTIndexFrequency() like this:
database.setFTIndexFrequency(database.FTINDEX_IMMEDIATE);

Resources