Skip to content

Panic - Attempt to subtract with overflow #4460

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

Closed
rrichardson opened this issue Sep 1, 2017 · 12 comments
Closed

Panic - Attempt to subtract with overflow #4460

rrichardson opened this issue Sep 1, 2017 · 12 comments
Labels
A-cargo-api Area: cargo-the-library API and internal code issues A-dependency-resolution Area: dependency resolution and the resolver C-bug Category: bug

Comments

@rrichardson
Copy link

rrichardson commented Sep 1, 2017

at https://github.com/rust-lang/cargo/blob/master/src/cargo/core/resolver/mod.rs#L453

Running in release mode this just spins in a loop forever, since it doesn't panic on the arithmetic.

The issue arrises when I attempt to depend upon both blake2 and postgres.

update 11:58
Both crates depend on different versions of generic array and typenum, and it seems to break when trying to resolve the dependencies.

*update 14:39"
Here is a minimal Cargo.toml that repros the problem :
#4460 (comment)

Running the latest nightly as of Sep 1 2017.

 ../../cargo/target/debug/cargo --version
cargo 0.23.0

cargo stack trace

rick@ubantoo:~/Projects/userhub$ RUST_BACKTRACE=1 ../../cargo/target/debug/cargo update
    Updating registry `https://github.com/rust-lang/crates.io-index`
    Updating git repository `https://github.com/pingcap/rust-prometheus`
    Updating git repository `https://github.com/QuiverMedia/rumqtt`
    Updating git repository `https://github.com/AlexPikalov/cdrs`
thread 'main' panicked at 'attempt to subtract with overflow', src/cargo/core/resolver/mod.rs:453:9
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:381
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:397
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:611
   5: std::panicking::begin_panic
             at /checkout/src/libstd/panicking.rs:572
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:522
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:498
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:71
   9: core::panicking::panic
             at /checkout/src/libcore/panicking.rs:51
  10: <cargo::core::resolver::RcVecIter<T>>::cur_index
             at src/cargo/core/resolver/mod.rs:453
  11: cargo::core::resolver::find_candidate
             at src/cargo/core/resolver/mod.rs:716
  12: cargo::core::resolver::activate_deps_loop
             at src/cargo/core/resolver/mod.rs:655
  13: cargo::core::resolver::resolve
             at src/cargo/core/resolver/mod.rs:355
  14: cargo::ops::resolve::resolve_with_previous
             at src/cargo/ops/resolve.rs:265
  15: cargo::ops::cargo_generate_lockfile::update_lockfile
             at src/cargo/ops/cargo_generate_lockfile.rs:77
  16: cargo::update::execute
             at src/bin/update.rs:81
  17: cargo::call_main_without_stdin
             at /home/rick/Projects/cargo/src/cargo/lib.rs:128
  18: cargo::try_execute_builtin_command
             at src/bin/cargo.rs:264
  19: cargo::execute
             at src/bin/cargo.rs:228
  20: cargo::call_main_without_stdin
             at /home/rick/Projects/cargo/src/cargo/lib.rs:128
  21: cargo::main::{{closure}}
             at src/bin/cargo.rs:95
  22: cargo::main
             at src/bin/cargo.rs:86
  23: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:99
  24: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:459
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:61
  25: main
  26: __libc_start_main
  27: _start

Cargo.toml

[dependencies]
blake2 = "^0.6"
chan = "^0.1"
clap = "2.26.0"
config = "0.7.0"
nix = "0.8.1"
num_cpus = "1.6.2"
quick-error = "1.2.0"
r2d2 = "0.7.2"
serde = "1.0.9"
serde_derive = "1.0.9"
slog = "2.0.9"
slog-json = "2.0.2"
threadpool = "^1.4"
time = "^0.1"
toml = "0.4"
chrono = "0.4"

[dependencies.cdrs]
git = "https://github.com/AlexPikalov/cdrs"
optional = true
rev = "1577cf7"

[dependencies.mqtt-protocol]
optional = true
version = "0.3"

[dependencies.prometheus]
git = "https://github.com/pingcap/rust-prometheus"
rev = "e4d7878"

[dependencies.proto]
path = "proto-rust"

[dependencies.protobuf]
optional = true
version = "^1.4"

[dependencies.r2d2_postgres]
optional = true
version = "0.13"

[dependencies.rumqtt]
optional = true
git = "https://github.com/QuiverMedia/rumqtt"

[dependencies.uuid]
features = ["v1"]
version = "^0.5.1"

[features]
cassandra = ["cdrs"]
default = [
    "cassandra",
    "postgres",
    "mqtt",
]
postgres = ["r2d2_postgres"]
mqtt = [
    "rumqtt",
    "mqtt-protocol",
    "protobuf",
]
[target."cfg(unix)".dependencies]
chan-signal = "^0.2"
@rrichardson
Copy link
Author

I'll attempt to repro this with a smaller use case.

@rrichardson
Copy link
Author

I have tracked down the source of the configuration problem. It has nothing to do with depending on a local crate path it is conflicting dependencies in crates.. The cause is that the crates postgres-protocol and blake2 both depend on different versions of generic-array and typenum.

in this case, postgres_r2d2 is also an optional dependency (but the feature is enabled by default)

       │   ├── postgres-protocol v0.3.0
│   │   │   ├── base64 v0.5.2
│   │   │   │   └── byteorder v1.1.0 (*)
│   │   │   ├── byteorder v1.1.0 (*)
│   │   │   ├── bytes v0.4.5 (*)
│   │   │   ├── fallible-iterator v0.1.3 (*)
│   │   │   ├── generic-array v0.7.2
│   │   │   │   ├── nodrop v0.1.9
│   │   │   │   │   └── odds v0.2.25
│   │   │   │   └── typenum v1.5.2
│   │   │   ├── hmac v0.1.1
│   │   │   │   ├── crypto-mac v0.3.0
│   │   │   │   │   ├── constant_time_eq v0.1.3
│   │   │   │   │   └── generic-array v0.7.2 (*)
│   │   │   │   ├── digest v0.5.2
│   │   │   │   │   └── generic-array v0.7.2 (*)
│   │   │   │   └── generic-array v0.7.2 (*)
├── blake2 v0.6.1
│   ├── byte-tools v0.2.0
│   ├── crypto-mac v0.4.0
│   │   ├── constant_time_eq v0.1.3
│   │   └── generic-array v0.8.2
│   │       ├── nodrop v0.1.9
│   │       │   └── odds v0.2.25
│   │       └── typenum v1.9.0
│   ├── digest v0.6.2
│   │   └── generic-array v0.8.2 (*)
│   └── generic-array v0.8.2 (*)

@rrichardson
Copy link
Author

rrichardson commented Sep 1, 2017

Setting the version to * for r2d2_postgres and letting it pick a compatible crate does alleviate the symptom. (although it is still not viable since we depend on protocol v0.3.0 types)

@rrichardson
Copy link
Author

Running in debug, I do see 408 occurrences of :

DEBUG:cargo::core::registry: load/precise  registry https://github.com/rust-lang/crates.io-index
DEBUG:cargo::core::registry: load/precise  registry https://github.com/rust-lang/crates.io-index
DEBUG:cargo::core::resolver: checking if generic-array v0.8.2 is already activated

before it runs out of siblings.

@rrichardson
Copy link
Author

It seems that cur, set by remaining_siblings.cur_index() is only really used for debugging purposes. The real issue is that it is in a state where it is cycling through the dependency graph infinitely. I'm still trying to understand the algorithm and figure out how it could get into such a state..

@rrichardson
Copy link
Author

Here is the most minimal Cargo.toml I can create that repros the problem :

[package]
authors = ["Rick Richardson <[email protected]>"]
name = "break-cargo"
version = "0.1.0"

[dependencies]
blake2 = "0.6.1"

[dependencies.regex]
version = "0.2.2"
optional = true

[dependencies.protobuf]
optional = true
version = "^1.4"

[dependencies.r2d2_postgres]
version = "^0.13"
optional = true

[features]
default = [
    "postgres",
    "blah",
]
blah = [
    "regex",
     "protobuf",
]
postgres = ["r2d2_postgres"]

@rrichardson
Copy link
Author

If you just make a project with deps on r2d2_postgres and blake2. It detects the un-resolveable conflict for the typenum version dependencies.

But when you add in some additional optional dependencies, it can't seem to traverse the graph.

@rrichardson
Copy link
Author

Also, I would note that there have been 2 major refactorings to the resolve module. One a couple weeks ago and one in November of last year. This toml breaks in the same way on the versions prior to those.

@alexcrichton
Copy link
Member

Thanks for the investigation and the report here @rrichardson! I'll take a look now and see what's up

@alexcrichton
Copy link
Member

Ok so the infinite loop here I believe is an instance of #4066 where this is an un-resolvable crate graph but Cargo isn't doing a great job of telling you that, unfortunately. (it takes forever to reach this conclusion)

The panic in debug mode though sounds like it's definitely a bug!

@carols10cents carols10cents added A-cargo-api Area: cargo-the-library API and internal code issues A-dependency-resolution Area: dependency resolution and the resolver C-bug Category: bug labels Oct 3, 2017
@Eh2406
Copy link
Contributor

Eh2406 commented Jan 29, 2018

@rrichardson minimal case does not reproduce for me. So I think some new versions of the dependencies have prevented it reproducing. Maybe if we can limit the range of the dependencies we can reproduce. This sounds like a really interesting one to dig into.

@alexcrichton
Copy link
Member

I believe this panic was since fixed, so closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cargo-api Area: cargo-the-library API and internal code issues A-dependency-resolution Area: dependency resolution and the resolver C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

4 participants