chinedufn / percy

Build frontend browser apps with Rust + WebAssembly. Supports server side rendering.
https://chinedufn.github.io/percy/
Apache License 2.0
2.26k stars 84 forks source link

Panic happened in /allocator/free_list.rs that `new_page == 0` #195

Closed Xuanwo closed 10 months ago

Xuanwo commented 10 months ago

Hi, we cound a random panic on our OpenDAL's java binding percy tests:

thread '<unnamed>' panicked at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator/free_list.rs:225:13:
assertion failed: new_page == 0
stack backtrace:
   0: rust_begin_unwind
             at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:597:5
   1: core::panicking::panic_fmt
             at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/panicking.rs:72:14
   2: core::panicking::panic
             at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/panicking.rs:127:5
   3: persy::allocator::free_list::FreeList::set_next_available
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator/free_list.rs:225:13
   4: <persy::allocator::free_list::FreeList as persy::device::UpdateList>::remove_last
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator/free_list.rs:273:20
   5: persy::device::file_device::FileDevice::check_and_trim
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/device/file_device.rs:90:17
   6: <persy::device::file_device::FileDevice as persy::device::Device>::trim_or_free_page
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/device/file_device.rs:212:19
   7: persy::allocator::Allocator::free_pages
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator.rs:295:13
   8: persy::allocator::Allocator::free
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator.rs:301:9
   9: persy::allocator::Allocator::recover_free
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/allocator.rs:266:17
  10: persy::transaction::tx_impl::TransactionImpl::recover_commit_cleanup
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/transaction/tx_impl.rs:802:21
  11: persy::journal::recover_impl::RecoverImpl::final_recover
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/journal/recover_impl.rs:267:25
  12: persy::persy::PersyImpl::final_recover
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/persy.rs:202:9
  13: persy::recover::Recover::finalize
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/recover.rs:81:9
  14: persy::open_options::OpenOptions::open
             at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/persy-1.4.5/src/open_options.rs:157:9
  15: <opendal::services::persy::backend::PersyBuilder as opendal::types::builder::Builder>::build
             at /home/runner/work/incubator-opendal/incubator-opendal/core/src/services/persy/backend.rs:101:21
  16: opendal::types::operator::builder::<impl opendal::types::operator::operator::Operator>::from_map
             at /home/runner/work/incubator-opendal/incubator-opendal/core/src/types/operator/builder.rs:118:19
  17: opendal::types::operator::builder::<impl opendal::types::operator::operator::Operator>::via_map
             at /home/runner/work/incubator-opendal/incubator-opendal/core/src/types/operator/builder.rs:221:30
  18: opendal_java::operator::intern_constructor
             at ./src/operator.rs:62:18
  19: Java_org_apache_opendal_Operator_constructor
             at ./src/operator.rs:53:5
  20: <unknown>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
fatal runtime error: failed to initiate panic, error 5
Aborted (core dumped)

The whole workflow could be found at https://github.com/apache/incubator-opendal/actions/runs/6927725229/job/18842214624

Do you think it's a possible bug or our usage of persy is wrong?

persy in OpenDAL:

https://github.com/apache/incubator-opendal/blob/main/core/src/services/persy/backend.rs#L81-L140

fn build(&mut self) -> Result<Self::Accessor> {
    let datafile_path = self.datafile.take().ok_or_else(|| {
        Error::new(ErrorKind::ConfigInvalid, "datafile is required but not set")
            .with_context("service", Scheme::Persy)
    })?;

    let segment_name = self.segment.take().ok_or_else(|| {
        Error::new(ErrorKind::ConfigInvalid, "segment is required but not set")
            .with_context("service", Scheme::Persy)
    })?;

    let segment = segment_name.clone();

    let index_name = self.index.take().ok_or_else(|| {
        Error::new(ErrorKind::ConfigInvalid, "index is required but not set")
            .with_context("service", Scheme::Persy)
    })?;

    let index = index_name.clone();

    let persy = persy::OpenOptions::new()
        .create(true)
        .prepare_with(move |p| init(p, &segment_name, &index_name))
        .open(&datafile_path)
        .map_err(|e| {
            Error::new(ErrorKind::ConfigInvalid, "open db")
                .with_context("service", Scheme::Persy)
                .with_context("datafile", datafile_path.clone())
                .set_source(e)
        })?;

    // This function will only be called on database creation
    fn init(
        persy: &persy::Persy,
        segment_name: &str,
        index_name: &str,
    ) -> std::result::Result<(), Box<dyn std::error::Error>> {
        let mut tx = persy.begin()?;

        if !tx.exists_segment(segment_name)? {
            tx.create_segment(segment_name)?;
        }
        if !tx.exists_index(index_name)? {
            tx.create_index::<String, persy::PersyId>(index_name, persy::ValueMode::Replace)?;
        }

        let prepared = tx.prepare()?;
        prepared.commit()?;

        Ok(())
    }

    Ok(PersyBackend::new(Adapter {
        datafile: datafile_path,
        segment,
        index,
        persy,
    }))
}
Xuanwo commented 10 months ago

Sorry, I posted issue to a wrong repo...