File tree 2 files changed +32
-4
lines changed
library/std/src/sync/mpmc
2 files changed +32
-4
lines changed Original file line number Diff line number Diff line change @@ -63,14 +63,14 @@ struct Block<T> {
63
63
64
64
impl < T > Block < T > {
65
65
/// Creates an empty block.
66
- fn new ( ) -> Block < T > {
66
+ fn new ( ) -> Box < Block < T > > {
67
67
// SAFETY: This is safe because:
68
68
// [1] `Block::next` (AtomicPtr) may be safely zero initialized.
69
69
// [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
70
70
// [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it
71
71
// holds a MaybeUninit.
72
72
// [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
73
- unsafe { MaybeUninit :: zeroed ( ) . assume_init ( ) }
73
+ unsafe { Box :: new_zeroed ( ) . assume_init ( ) }
74
74
}
75
75
76
76
/// Waits until the next pointer is set.
@@ -199,13 +199,13 @@ impl<T> Channel<T> {
199
199
// If we're going to have to install the next block, allocate it in advance in order to
200
200
// make the wait for other threads as short as possible.
201
201
if offset + 1 == BLOCK_CAP && next_block. is_none ( ) {
202
- next_block = Some ( Box :: new ( Block :: < T > :: new ( ) ) ) ;
202
+ next_block = Some ( Block :: < T > :: new ( ) ) ;
203
203
}
204
204
205
205
// If this is the first message to be sent into the channel, we need to allocate the
206
206
// first block and install it.
207
207
if block. is_null ( ) {
208
- let new = Box :: into_raw ( Box :: new ( Block :: < T > :: new ( ) ) ) ;
208
+ let new = Box :: into_raw ( Block :: < T > :: new ( ) ) ;
209
209
210
210
if self
211
211
. tail
Original file line number Diff line number Diff line change
1
+ //@ run-pass
2
+ //@ compile-flags: -Copt-level=0
3
+
4
+ // The channel's `Block::new` was causing a stack overflow because it held 32 item slots, which is
5
+ // 1MiB for this test's `BigStruct` -- instantiated on the stack before moving to `Box::new`.
6
+ //
7
+ // That block is now initialized directly on the heap.
8
+ //
9
+ // Ref: https://github.com/rust-lang/rust/issues/102246
10
+
11
+ use std:: sync:: mpsc:: channel;
12
+ use std:: thread;
13
+
14
+ const N : usize = 32_768 ;
15
+ struct BigStruct {
16
+ _data : [ u8 ; N ] ,
17
+ }
18
+
19
+ fn main ( ) {
20
+ let ( sender, receiver) = channel :: < BigStruct > ( ) ;
21
+
22
+ let thread1 = thread:: spawn ( move || {
23
+ sender. send ( BigStruct { _data : [ 0u8 ; N ] } ) . unwrap ( ) ;
24
+ } ) ;
25
+
26
+ thread1. join ( ) . unwrap ( ) ;
27
+ for _data in receiver. try_iter ( ) { }
28
+ }
You can’t perform that action at this time.
0 commit comments