Drop impl not running (SOLVED)

The short version of this question: Are their conditions, especially with FFI involved, under which a Drop implementation will not run?

The longer version:

I've written something similar to the following:

pub struct A {
    .
    .
    field: B,
}

pub struct B(C);

//C is a rust-ffmpeg-sys struct which is a FFI to FFMPEG

I've implemented Drop for structs A and B. The Drop for A always runs as it should. The Drop for B does not run when it's used with processing functions in rust-ffmpeg-sys, even when the program exits correctly after its use. That is, if I pass B.0 via A.field to a specific rust-ffmpeg-sys function, B's Drop does not run. If I don't use A.field.0 the Drop runs on program exit as it should.

It's a wild guess, but maybe the C function accidentally zeroes the drop flags of B?

I would try to print raw memory of structs before and after calling the ffi function.

Also, are you sure you are not combining Drop and #[repr(C)] in the same struct?

https://github.com/rust-lang/rust/pull/22078

What exactly are you doing? Because i'm 99% sure you can't move fields out of a struct that has a Drop impl.

The original code is part of a corporate project so I can't post it. I'm in the process of writing code that I can share and reproduces the problem.

I'm not moving fields out of the struct. They are all *mut T.

I didn't even know that was possible. I'll look up how to do so but if you have a link to docs that would be fantastic.

Then I'm not sure what you mean by "pass via".

Use gdb, or in Rust, do something like this:

use std::mem::{transmute,size_of_val};
unsafe{println!("{:?}",&transmute::<_,&[u8;N]>(&my_struct)[..]);}

Where N is the output of size_of_val(&my_struct).

1 Like

Thanks for the help @jethrogb, @matklad.

Using the transmute hint I was able to verify that my struct is being changed by the C code. But I don't quite yet understand how.

Over the weekend I tried to gather more information using rust-gdb but unfortunately, rust-gdb can't find my variable name and when I try 'info locals' rust-gdb crashes. I'm troubleshooting that now.

Until I get the rust-gdb problem sorted I was hoping someone could shed some light on the transmute results. Specifically, I can't find the documentation that specifies the byte pattern for the hidden drop flag. So I can't be certain it's getting overwritten.

When I use transmute to get the array representation of the struct before the C function call I get

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 0]

and after the C function call

[224, 64, 239, 250, 191, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 128, 128, 87, 238, 250, 191, 127, 0, 0, 119, 43, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 250, 71, 248, 191, 127, 0, 0, 99, 111, 118, 114, 0, 0, 0, 0, 168, 115, 1, 0, 0, 0, 0, 0]

But I don't know how to interpret those results. Can anyone verify that the drop flag has been overwritten from that output?

I hope to have some code that I can share today also.

I don't think so. The “dropped” value is 0x1d and I don't see that in there.

I finally got rust-gdb working.

I've posted the code that exhibits the problem at https://github.com/ereichert/rust-ffmpeg-drop-problem/blob/master/src/main.rs

Before the C function call the struct in memory looks like:

p av_packet $1 = TLXAVPacket = {AVPacket = {buf = 0x0, pts = -9223372036854775808, dts = -9223372036854775808, data = 0x0, size = 0, stream_index = 0, flags = 0, side_data = 0x0, side_data_elems = 0, duration = 0, pos = 0, convergence_duration = 0}}

I don't see anything that indicates Drop is implemented for TLXAVPacket. Am I missing something?

After the C function call:

p av_packet $2 = TLXAVPacket = {AVPacket = {buf = 0x7ffff8957100, pts = -9223372036854775808, dts = -9223372036854775808, data = 0x7ffff89487a0 "\377\330\377", <incomplete sequence \340>, size = 11127, stream_index = 2, flags = 1, side_data = 0x0, side_data_elems = 0, duration = 0, pos = 140737341910976, convergence_duration = 1920364387}}

Looks like I would expect. Again, I don't see anything that indicates a Drop flag.

I've scoured the docs for information about how Drop works to help me troubleshoot this issue (which is important for our application). I've hit a wall.

Any insight would be greatly appreciated?

I guess gdb isn't aware of drop flags.

[quote="ereichert, post:9, topic:6178"]
pos = 140737341910976, convergence_duration = 1920364387
[/quote]This seems suspicious, the value of pos looks like a pointer. Do you perhaps need to enable the ff_api_destruct_packet feature? Oh I see it's detected by the build script. Then there might be a problem with that.

Took my teammate and me a few days but we verified what everyone suggested.

The drop glue was being overwritten by the C function.

It absolutely was caused by ff_api_destruct_packet_feature not being honored.

Fixing the build script is what fixed it.

Thanks everyone.

Could this build script issue bite anyone else?

It absolutely will bite others. We are preparing a pull request for the upstream repo.