1

I have a Rust application with Actix Web which resizes images using libvips (https://crates.io/crates/libvips). Now I am trying to dockerize it. Here is my Dockerfile:

####################################################################################################
FROM rust:1.59.0-alpine3.15 AS build

RUN apk update && apk add vips vips-dev libc-dev

WORKDIR /opt/app

COPY ./ .

RUN cargo build --release

####################################################################################################
## Final image
####################################################################################################
FROM alpine:3.15

RUN apk update && apk add vips vips-dev libc-dev

WORKDIR /opt/app

# Copy our build
COPY --from=build /opt/app/target/release/ ./

CMD ["/opt/app/image-resizer"]

Cargo.toml:

[package]
name = "image-resizer"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
actix-web = "^4"
serde = { version = "1", features = ["derive"] }
env_logger = "0.9.0"
libvips = "1.4.3"

The image builds fine, but when I try to run it, it exits with no output and code 139. To my knowledge, it indicates a segfault or similar error.

I found out that libvips is introducing a problem (the app doesn't crash if I remove usages of it), but don't know how to fix it. Any help would be appreciated.

Repo: https://gitlab.com/antonlyap/image-resizer

Valgrind output:

==1== Memcheck, a memory error detector
==1== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==1== Command: /opt/app/image-resizer
==1== 
==1== Jump to the invalid address stated on the next line
==1==    at 0x0: ???
==1==    by 0x3: ???
==1==    by 0x2: ???
==1==    by 0x1FFF000AD7: ???
==1==    by 0x1FFF000D0F: ???
==1==    by 0x4: ???
==1==    by 0x150191: unsetenv (unsetenv.c:28)
==1==    by 0x400001F: ???
==1==    by 0x14FF0D: libc_start_main_stage2 (__libc_start_main.c:94)
==1==    by 0x11291E: ??? (in /opt/app/image-resizer)
==1==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==1== 
==1== 
==1== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==1==  Bad permissions for mapped region at address 0x0
==1==    at 0x0: ???
==1==    by 0x3: ???
==1==    by 0x2: ???
==1==    by 0x1FFF000AD7: ???
==1==    by 0x1FFF000D0F: ???
==1==    by 0x4: ???
==1==    by 0x150191: unsetenv (unsetenv.c:28)
==1==    by 0x400001F: ???
==1==    by 0x14FF0D: libc_start_main_stage2 (__libc_start_main.c:94)
==1==    by 0x11291E: ??? (in /opt/app/image-resizer)
==1== 
==1== HEAP SUMMARY:
==1==     in use at exit: 0 bytes in 0 blocks
==1==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1== 
==1== All heap blocks were freed -- no leaks are possible
==1== 
==1== For lists of detected and suppressed errors, rerun with: -s
==1== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)

valgrind: the 'impossible' happened:
   main(): signal was supposed to be fatal

host stacktrace:
==1==    at 0x580327DD: show_sched_status_wrk (m_libcassert.c:406)
==1==    by 0x58032A30: report_and_quit (m_libcassert.c:477)
==1==    by 0x58032C47: panic (m_libcassert.c:553)
==1==    by 0x58032C47: vgPlain_core_panic_at (m_libcassert.c:558)
==1==    by 0x58032C4F: vgPlain_core_panic (m_libcassert.c:563)
==1==    by 0x58088B54: shutdown_actions_NORETURN (m_main.c:2339)
==1==    by 0x580AD652: run_a_thread_NORETURN (syswrap-linux.c:201)

sched status:
  running_tid=1


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.

Minimal reproduction code:

use libvips::VipsApp;

fn main() {
  VipsApp::new("App", true).expect("Failed to create app");
}
Anton
  • 440
  • 3
  • 10
  • 1
    What does e.g. valgrind say about the segfault? See [Debugging a segfault in my Rust program](https://jvns.ca/blog/2017/12/23/segfault-debugging/) PS: Can you post a reproducible example that we can run on our own computers? – Nick ODell Mar 29 '22 at 19:06
  • [To make Stack Overflow a useful resource for future visitors beyond the context of your repository](https://meta.stackoverflow.com/q/380194/155423), please [edit] your question to add a [MRE] in the question itself, in addition to the link to your repository. – Shepmaster Mar 29 '22 at 20:11
  • @NickODell Valgrind output and other details are now included – Anton Mar 29 '22 at 20:22
  • @Shepmaster Any usage of libvips leads to a similar crash, so any kind of usage would be a minimal reproducible example. In my case, it crashes on creating the VipsApp – Anton Mar 29 '22 at 20:22
  • @Антон great, then it should be trivial for you to *include the minimal usage in the question*! – Shepmaster Mar 29 '22 at 20:39
  • Your stacktrace indicates that you are using Tokio, so are you stating that (a) using Tokio is **required** to trigger the error or (b) you haven't yet reduced the problem to a minimal reproduction? – Shepmaster Mar 29 '22 at 20:53
  • @Shepmaster That stacktrace was from my repo, I should've included the one from minimal reproduction. My bad here, edited the question – Anton Mar 29 '22 at 21:22
  • 1
    I did some debugging under GDB, and I got a [slightly more helpful stacktrace](https://gist.github.com/nickodell/e540ca2eaa553336e12d3eed6563c4c2). It appears the problem happens inside libvips::init(). Specifically, in libvips::init(), it calls something from the global offset table, and that global offset table contains an address of 0. Not sure *why* that happens, but there's where the program is breaking. – Nick ODell Mar 29 '22 at 21:56

1 Answers1

2

https://github.com/olxgroup-oss/libvips-rust-bindings/issues/9

I have changed line 10 in my Dockerfile to

RUN RUSTFLAGS="-C target-feature=-crt-static $(pkg-config vips --libs)" cargo build --release

and the error is gone.

Other solutions are welcome. Thanks to everyone who commented on my post.

Anton
  • 440
  • 3
  • 10