Skip to content

Commit

Permalink
Fix deadlock when closing the program
Browse files Browse the repository at this point in the history
* When closing the program it will sometimes
halt and the process have to be killed.
This happens cause of a deadlock in the SDL2
audio device whcih is now fixed
* Bump openssl version used in running the tests
(thanks to Dependabot)
  • Loading branch information
alloncm committed Apr 1, 2023
1 parent db7ce2e commit 6e7f81c
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 14 deletions.
28 changes: 20 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ members = [
]

[workspace.package]
version = "3.0.0"
authors = ["alloncm <[email protected]>"]
version = "3.0.1"
authors = ["alloncm <[email protected]>"]
rust-version = "1.65" # cause of let else feature
1 change: 1 addition & 0 deletions gb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "gb"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
19 changes: 15 additions & 4 deletions gb/src/sdl/sdl_pull_audio_device.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::ffi::c_void;
use std::{mem::ManuallyDrop, ffi::c_void};

use lib_gb::{GB_FREQUENCY, apu::audio_device::*};
use sdl2::sys::*;
use crossbeam_channel::{Receiver, Sender, bounded};
Expand All @@ -19,9 +20,13 @@ pub struct SdlPullAudioDevice<AR:AudioResampler>{
buffer_number_index:usize,
buffer_index:usize,

tarnsmiter: Sender<usize>,
userdata_ptr: *mut UserData,
device_id:SDL_AudioDeviceID,

// Needs to be droped manually cause the callback might be blocking on the channel,
// Closing the channel is only possible by droping and Im closing the callback before the destructor is called
// So I need to call it before closing the callback
tarnsmiter: ManuallyDrop<Sender<usize>>,
}

impl<AR:AudioResampler> ResampledAudioDevice<AR> for SdlPullAudioDevice<AR>{
Expand All @@ -40,7 +45,7 @@ impl<AR:AudioResampler> ResampledAudioDevice<AR> for SdlPullAudioDevice<AR>{
buffer_index:0,
buffer_number_index:0,
resampler: AudioResampler::new(GB_FREQUENCY * turbo_mul as u32, frequency as u32),
tarnsmiter:s,
tarnsmiter: ManuallyDrop::new(s),
userdata_ptr:Box::into_raw(data),
device_id:0
};
Expand Down Expand Up @@ -88,6 +93,11 @@ impl<AR:AudioResampler> AudioDevice for SdlPullAudioDevice<AR>{
impl<AR:AudioResampler> Drop for SdlPullAudioDevice<AR>{
fn drop(&mut self) {
unsafe{
// Drops the trasmitter manully since we need it to close the channel before we can close the device
// if the callback will still wait for more samples we will be in a deadlock since the gameboy will
// no longer supply audio samples
ManuallyDrop::drop(&mut self.tarnsmiter);

SDL_CloseAudioDevice(self.device_id);
drop(Box::from_raw(self.userdata_ptr));
}
Expand All @@ -99,7 +109,8 @@ unsafe extern "C" fn audio_callback(userdata:*mut c_void, buffer:*mut u8, length
let safe_userdata = &mut *(userdata as *mut UserData);

if safe_userdata.current_buf.is_none(){
safe_userdata.current_buf = Some(safe_userdata.rx.recv().unwrap());
let Ok(rx_data) = safe_userdata.rx.recv() else {return};
safe_userdata.current_buf = Some(rx_data);
}

let samples = &*((safe_userdata.current_buf.unwrap()) as *const [Sample;BUFFER_SIZE]);
Expand Down
1 change: 1 addition & 0 deletions lib_gb/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "lib_gb"
version.workspace = true
authors.workspace = true
rust-version.workspace = true
edition = "2018"

[dependencies]
Expand Down

0 comments on commit 6e7f81c

Please sign in to comment.