Skip to content

Commit 599e975

Browse files
bors[bot]taiki-e
andauthored
Merge #968
968: channel: Extend panic_on_drop test r=taiki-e a=taiki-e Include rust-lang/rust#107466 's case. cc rust-lang/rust#108164 Co-authored-by: Taiki Endo <te316e89@gmail.com>
2 parents e094a1a + 3ab7476 commit 599e975

File tree

2 files changed

+153
-18
lines changed

2 files changed

+153
-18
lines changed

crossbeam-channel/tests/array.rs

+61-18
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Tests for the array channel flavor.
22
33
use std::any::Any;
4+
use std::cell::Cell;
45
use std::sync::atomic::AtomicUsize;
56
use std::sync::atomic::Ordering;
67
use std::thread;
@@ -692,53 +693,95 @@ fn channel_through_channel() {
692693

693694
#[test]
694695
fn panic_on_drop() {
695-
struct Msg1<'a>(&'a mut bool);
696+
struct Msg1<'a>(&'a Cell<bool>);
696697
impl Drop for Msg1<'_> {
697698
fn drop(&mut self) {
698-
if *self.0 && !std::thread::panicking() {
699+
if self.0.get() && !std::thread::panicking() {
699700
panic!("double drop");
700701
} else {
701-
*self.0 = true;
702+
self.0.set(true);
702703
}
703704
}
704705
}
705706

706-
struct Msg2<'a>(&'a mut bool);
707+
struct Msg2<'a>(&'a Cell<bool>);
707708
impl Drop for Msg2<'_> {
708709
fn drop(&mut self) {
709-
if *self.0 {
710+
if self.0.get() {
710711
panic!("double drop");
711712
} else {
712-
*self.0 = true;
713+
self.0.set(true);
713714
panic!("first drop");
714715
}
715716
}
716717
}
717718

718-
// normal
719+
// normal (sender first)
719720
let (s, r) = bounded(2);
720-
let (mut a, mut b) = (false, false);
721-
s.send(Msg1(&mut a)).unwrap();
722-
s.send(Msg1(&mut b)).unwrap();
721+
let (a, b) = (Cell::new(false), Cell::new(false));
722+
s.send(Msg1(&a)).unwrap();
723+
s.send(Msg1(&b)).unwrap();
723724
drop(s);
725+
assert!(!a.get());
726+
assert!(!b.get());
724727
drop(r);
725-
assert!(a);
726-
assert!(b);
728+
assert!(a.get());
729+
assert!(b.get());
727730

728-
// panic on drop
731+
// normal (receiver first)
729732
let (s, r) = bounded(2);
730-
let (mut a, mut b) = (false, false);
731-
s.send(Msg2(&mut a)).unwrap();
732-
s.send(Msg2(&mut b)).unwrap();
733+
let (a, b) = (Cell::new(false), Cell::new(false));
734+
s.send(Msg1(&a)).unwrap();
735+
s.send(Msg1(&b)).unwrap();
736+
drop(r);
737+
// TODO: should be dropped eagerly: https://github.com/rust-lang/rust/issues/107466
738+
assert!(!a.get());
739+
assert!(!b.get());
733740
drop(s);
741+
assert!(a.get());
742+
assert!(b.get());
743+
744+
// panic on drop (sender first)
745+
let (s, r) = bounded(2);
746+
let (a, b) = (Cell::new(false), Cell::new(false));
747+
s.send(Msg2(&a)).unwrap();
748+
s.send(Msg2(&b)).unwrap();
749+
drop(s);
750+
assert!(!a.get());
751+
assert!(!b.get());
734752
let res = std::panic::catch_unwind(move || {
735753
drop(r);
736754
});
737755
assert_eq!(
738756
*res.unwrap_err().downcast_ref::<&str>().unwrap(),
739757
"first drop"
740758
);
741-
assert!(a);
759+
assert!(a.get());
760+
// Elements after the panicked element will leak.
761+
assert!(!b.get());
762+
763+
// panic on drop (receiver first)
764+
let (s, r) = bounded(2);
765+
let (a, b) = (Cell::new(false), Cell::new(false));
766+
s.send(Msg2(&a)).unwrap();
767+
s.send(Msg2(&b)).unwrap();
768+
let res = std::panic::catch_unwind(move || {
769+
drop(r);
770+
});
771+
// This currently doesn't panic, but it should panic when a fix for
772+
// https://github.com/rust-lang/rust/issues/107466 is implemented.
773+
assert!(res.is_ok());
774+
// TODO: `a` should be dropped eagerly: https://github.com/rust-lang/rust/issues/107466
775+
assert!(!a.get());
776+
assert!(!b.get());
777+
let res = std::panic::catch_unwind(move || {
778+
drop(s);
779+
});
780+
assert_eq!(
781+
*res.unwrap_err().downcast_ref::<&str>().unwrap(),
782+
"first drop"
783+
);
784+
assert!(a.get());
742785
// Elements after the panicked element will leak.
743-
assert!(!b);
786+
assert!(!b.get());
744787
}

crossbeam-channel/tests/list.rs

+92
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Tests for the list channel flavor.
22
33
use std::any::Any;
4+
use std::cell::Cell;
45
use std::sync::atomic::AtomicUsize;
56
use std::sync::atomic::Ordering;
67
use std::thread;
@@ -580,3 +581,94 @@ fn channel_through_channel() {
580581
})
581582
.unwrap();
582583
}
584+
585+
#[test]
586+
fn panic_on_drop() {
587+
struct Msg1<'a>(&'a Cell<bool>);
588+
impl Drop for Msg1<'_> {
589+
fn drop(&mut self) {
590+
if self.0.get() && !std::thread::panicking() {
591+
panic!("double drop");
592+
} else {
593+
self.0.set(true);
594+
}
595+
}
596+
}
597+
598+
struct Msg2<'a>(&'a Cell<bool>);
599+
impl Drop for Msg2<'_> {
600+
fn drop(&mut self) {
601+
if self.0.get() {
602+
panic!("double drop");
603+
} else {
604+
self.0.set(true);
605+
panic!("first drop");
606+
}
607+
}
608+
}
609+
610+
// normal (sender first)
611+
let (s, r) = unbounded();
612+
let (a, b) = (Cell::new(false), Cell::new(false));
613+
s.send(Msg1(&a)).unwrap();
614+
s.send(Msg1(&b)).unwrap();
615+
drop(s);
616+
assert!(!a.get());
617+
assert!(!b.get());
618+
drop(r);
619+
assert!(a.get());
620+
assert!(b.get());
621+
622+
// normal (receiver first)
623+
let (s, r) = unbounded();
624+
let (a, b) = (Cell::new(false), Cell::new(false));
625+
s.send(Msg1(&a)).unwrap();
626+
s.send(Msg1(&b)).unwrap();
627+
drop(r);
628+
// When the receiver is dropped, messages are dropped eagerly.
629+
assert!(a.get());
630+
assert!(b.get());
631+
drop(s);
632+
assert!(a.get());
633+
assert!(b.get());
634+
635+
// panic on drop (sender first)
636+
let (s, r) = unbounded();
637+
let (a, b) = (Cell::new(false), Cell::new(false));
638+
s.send(Msg2(&a)).unwrap();
639+
s.send(Msg2(&b)).unwrap();
640+
drop(s);
641+
assert!(!a.get());
642+
assert!(!b.get());
643+
let res = std::panic::catch_unwind(move || {
644+
drop(r);
645+
});
646+
assert_eq!(
647+
*res.unwrap_err().downcast_ref::<&str>().unwrap(),
648+
"first drop"
649+
);
650+
assert!(a.get());
651+
// Elements after the panicked element will leak.
652+
assert!(!b.get());
653+
654+
// panic on drop (receiver first)
655+
let (s, r) = unbounded();
656+
let (a, b) = (Cell::new(false), Cell::new(false));
657+
s.send(Msg2(&a)).unwrap();
658+
s.send(Msg2(&b)).unwrap();
659+
let res = std::panic::catch_unwind(move || {
660+
drop(r);
661+
});
662+
assert_eq!(
663+
*res.unwrap_err().downcast_ref::<&str>().unwrap(),
664+
"first drop"
665+
);
666+
// When the receiver is dropped, messages are dropped eagerly.
667+
assert!(a.get());
668+
// Elements after the panicked element will leak.
669+
assert!(!b.get());
670+
drop(s);
671+
assert!(a.get());
672+
// Elements after the panicked element will leak.
673+
assert!(!b.get());
674+
}

0 commit comments

Comments
 (0)