Skip to content

Commit 9e8f06b

Browse files
fix: data race in the pdf import code (#1514)
1 parent c5aa40c commit 9e8f06b

File tree

1 file changed

+89
-48
lines changed

1 file changed

+89
-48
lines changed

crates/rnote-ui/src/dialogs/import.rs

Lines changed: 89 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -444,69 +444,110 @@ pub(crate) async fn dialog_import_pdf_w_prefs(
444444

445445
// Listen to responses
446446

447-
let (tx, mut rx) = futures::channel::mpsc::unbounded::<anyhow::Result<bool>>();
447+
let (tx, mut rx_confirm) = futures::channel::mpsc::unbounded::<(bool, bool)>();
448448
let tx_cancel = tx.clone();
449449
let tx_confirm = tx.clone();
450+
let tx_close = tx.clone();
450451

451-
import_pdf_button_cancel.connect_clicked(clone!(
452-
#[weak]
453-
dialog,
454-
move |_| {
455-
dialog.close();
456-
457-
if let Err(e) = tx_cancel.unbounded_send(Ok(false)) {
458-
error!(
452+
import_pdf_button_cancel.connect_clicked(clone!(move |_| {
453+
if let Err(e) = tx_cancel.unbounded_send((false, false)) {
454+
error!(
459455
"PDF import dialog closed, but failed to send signal through channel. Err: {e:?}"
460456
);
461-
}
462457
}
463-
));
464-
465-
import_pdf_button_confirm.connect_clicked(clone!(#[weak] pdf_page_start_row, #[weak] pdf_page_end_row, #[weak] input_file, #[weak] dialog, #[strong] password, #[weak] appwindow, #[weak] canvas, move |_| {
466-
dialog.close();
467-
468-
let inner_tx_confirm = tx_confirm.clone();
469-
470-
glib::spawn_future_local(clone!(#[weak] pdf_page_start_row, #[weak] pdf_page_end_row, #[weak] input_file, #[strong] password, #[weak] appwindow, #[weak] canvas, async move {
471-
let page_range =
472-
(pdf_page_start_row.value() as u32 - 1)..pdf_page_end_row.value() as u32;
473-
474-
let (bytes, _) = match input_file.load_bytes_future().await {
475-
Ok(res) => {res}
476-
Err(err) => {
477-
if let Err(e) = inner_tx_confirm.unbounded_send(Err(err.into())) {
478-
error!("Failed to load file, but failed to send signal through channel. Err: {e:?}");
479-
}
480-
return;
481-
}
482-
};
483-
if let Err(e) = canvas.load_in_pdf_bytes(&appwindow, bytes.to_vec(), target_pos, Some(page_range), password).await {
484-
if let Err(e) = inner_tx_confirm.unbounded_send(Err(e)) {
485-
error!("Failed to load PDF, but failed to send signal through channel. Err: {e:?}");
486-
}
487-
return;
488-
}
458+
}));
489459

490-
if let Err(e) = inner_tx_confirm.unbounded_send(Ok(true)) {
491-
error!("PDF file imported, but failed to send signal through channel. Err: {e:?}");
492-
}
493-
}));
460+
import_pdf_button_confirm.connect_clicked(clone!(move |_| {
461+
if let Err(e) = tx_confirm.unbounded_send((true, false)) {
462+
error!("PDF file imported, but failed to send signal through channel. Err: {e:?}");
463+
}
494464
}));
495465

496466
// Send a cancel response when the dialog is closed
497-
dialog.connect_closed(clone!(
498-
#[weak]
499-
import_pdf_button_cancel,
500-
move |_| {
501-
import_pdf_button_cancel.emit_clicked();
467+
dialog.connect_closed(clone!(move |_| {
468+
if let Err(e) = tx_close.unbounded_send((false, true)) {
469+
error!(
470+
"PDF import dialog closed, but failed to send signal through channel. Err: {e:?}"
471+
);
502472
}
503-
));
473+
}));
504474

505475
// Present than wait for a response from the dialog
506476
dialog.present(appwindow.root().as_ref());
507477

508-
match rx.next().await {
509-
Some(res) => res,
478+
match rx_confirm.next().await {
479+
Some((confirm, dialog_closed)) => {
480+
if !dialog_closed {
481+
dialog.close();
482+
}
483+
if confirm {
484+
let (tx_import, mut rx_import) =
485+
futures::channel::mpsc::unbounded::<anyhow::Result<bool>>();
486+
487+
glib::spawn_future_local(clone!(
488+
#[weak]
489+
pdf_page_start_row,
490+
#[weak]
491+
pdf_page_end_row,
492+
#[weak]
493+
input_file,
494+
#[strong]
495+
password,
496+
#[weak]
497+
appwindow,
498+
#[weak]
499+
canvas,
500+
async move {
501+
let page_range = (pdf_page_start_row.value() as u32 - 1)
502+
..pdf_page_end_row.value() as u32;
503+
let (bytes, _) = match input_file.load_bytes_future().await {
504+
Ok(res) => res,
505+
Err(err) => {
506+
if let Err(e) = tx_import.unbounded_send(Err(err.into())) {
507+
error!(
508+
"Failed to load file, but failed to send signal through channel. Err: {e:?}"
509+
);
510+
}
511+
return;
512+
}
513+
};
514+
515+
if let Err(e) = canvas
516+
.load_in_pdf_bytes(
517+
&appwindow,
518+
bytes.to_vec(),
519+
target_pos,
520+
Some(page_range),
521+
password,
522+
)
523+
.await
524+
{
525+
if let Err(e) = tx_import.unbounded_send(Err(e)) {
526+
error!(
527+
"Failed to load PDF, but failed to send signal through channel. Err: {e:?}"
528+
);
529+
return;
530+
}
531+
};
532+
533+
if let Err(e) = tx_import.unbounded_send(Ok(true)) {
534+
error!(
535+
"PDF file imported, but failed to send signal through channel. Err: {e:?}"
536+
);
537+
}
538+
}
539+
));
540+
541+
match rx_import.next().await {
542+
Some(res) => res,
543+
None => Err(anyhow::anyhow!(
544+
"Channel closed before receiving a response from loader thread."
545+
)),
546+
}
547+
} else {
548+
Ok(false)
549+
}
550+
}
510551
None => Err(anyhow::anyhow!(
511552
"Channel closed before receiving a response from dialog."
512553
)),

0 commit comments

Comments
 (0)