Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

View File

@@ -0,0 +1,331 @@
# Common Concurrency Errors & Fixes
## E0277: Cannot Send Between Threads
### Error Pattern
```rust
use std::rc::Rc;
let data = Rc::new(42);
std::thread::spawn(move || {
println!("{}", data); // ERROR: Rc<i32> cannot be sent between threads
});
```
### Fix Options
**Option 1: Use Arc instead**
```rust
use std::sync::Arc;
let data = Arc::new(42);
let data_clone = Arc::clone(&data);
std::thread::spawn(move || {
println!("{}", data_clone); // OK: Arc is Send
});
```
**Option 2: Move owned data**
```rust
let data = 42; // i32 is Copy and Send
std::thread::spawn(move || {
println!("{}", data); // OK
});
```
---
## E0277: Cannot Share Between Threads (Not Sync)
### Error Pattern
```rust
use std::cell::RefCell;
use std::sync::Arc;
let data = Arc::new(RefCell::new(42));
// ERROR: RefCell is not Sync
```
### Fix Options
**Option 1: Use Mutex for thread-safe interior mutability**
```rust
use std::sync::{Arc, Mutex};
let data = Arc::new(Mutex::new(42));
let data_clone = Arc::clone(&data);
std::thread::spawn(move || {
let mut guard = data_clone.lock().unwrap();
*guard += 1;
});
```
**Option 2: Use RwLock for read-heavy workloads**
```rust
use std::sync::{Arc, RwLock};
let data = Arc::new(RwLock::new(42));
let data_clone = Arc::clone(&data);
std::thread::spawn(move || {
let guard = data_clone.read().unwrap();
println!("{}", *guard);
});
```
---
## Deadlock Patterns
### Pattern 1: Lock Ordering Deadlock
```rust
// DANGER: potential deadlock
use std::sync::{Arc, Mutex};
let a = Arc::new(Mutex::new(1));
let b = Arc::new(Mutex::new(2));
// Thread 1: locks a then b
let a1 = Arc::clone(&a);
let b1 = Arc::clone(&b);
std::thread::spawn(move || {
let _a = a1.lock().unwrap();
let _b = b1.lock().unwrap(); // waits for b
});
// Thread 2: locks b then a (opposite order!)
let a2 = Arc::clone(&a);
let b2 = Arc::clone(&b);
std::thread::spawn(move || {
let _b = b2.lock().unwrap();
let _a = a2.lock().unwrap(); // waits for a - DEADLOCK
});
```
### Fix: Consistent Lock Ordering
```rust
// SAFE: always lock in same order (a before b)
std::thread::spawn(move || {
let _a = a1.lock().unwrap();
let _b = b1.lock().unwrap();
});
std::thread::spawn(move || {
let _a = a2.lock().unwrap(); // same order
let _b = b2.lock().unwrap();
});
```
### Pattern 2: Self-Deadlock
```rust
// DANGER: locking same mutex twice
let m = Mutex::new(42);
let _g1 = m.lock().unwrap();
let _g2 = m.lock().unwrap(); // DEADLOCK on std::Mutex
// FIX: use parking_lot::ReentrantMutex if needed
// or restructure code to avoid double locking
```
---
## Mutex Guard Across Await
### Error Pattern
```rust
use std::sync::Mutex;
use tokio::time::sleep;
async fn bad_async() {
let m = Mutex::new(42);
let guard = m.lock().unwrap();
sleep(Duration::from_secs(1)).await; // WARNING: guard held across await
println!("{}", *guard);
}
```
### Fix Options
**Option 1: Scope the lock**
```rust
async fn good_async() {
let m = Mutex::new(42);
let value = {
let guard = m.lock().unwrap();
*guard // copy value
}; // guard dropped here
sleep(Duration::from_secs(1)).await;
println!("{}", value);
}
```
**Option 2: Use tokio::sync::Mutex**
```rust
use tokio::sync::Mutex;
async fn good_async() {
let m = Mutex::new(42);
let guard = m.lock().await; // async lock
sleep(Duration::from_secs(1)).await; // OK with tokio::Mutex
println!("{}", *guard);
}
```
---
## Data Race Prevention
### Pattern: Missing Synchronization
```rust
// This WON'T compile - Rust prevents data races
use std::sync::Arc;
let data = Arc::new(0);
let d1 = Arc::clone(&data);
let d2 = Arc::clone(&data);
std::thread::spawn(move || {
// *d1 += 1; // ERROR: cannot mutate through Arc
});
std::thread::spawn(move || {
// *d2 += 1; // ERROR: cannot mutate through Arc
});
```
### Fix: Add Synchronization
```rust
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicI32, Ordering};
// Option 1: Mutex
let data = Arc::new(Mutex::new(0));
let d1 = Arc::clone(&data);
std::thread::spawn(move || {
*d1.lock().unwrap() += 1;
});
// Option 2: Atomic (for simple types)
let data = Arc::new(AtomicI32::new(0));
let d1 = Arc::clone(&data);
std::thread::spawn(move || {
d1.fetch_add(1, Ordering::SeqCst);
});
```
---
## Channel Errors
### Disconnected Channel
```rust
use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
drop(tx); // sender dropped
match rx.recv() {
Ok(v) => println!("{}", v),
Err(_) => println!("channel disconnected"), // this happens
}
```
### Fix: Handle Disconnection
```rust
// Use try_recv for non-blocking
loop {
match rx.try_recv() {
Ok(msg) => handle(msg),
Err(TryRecvError::Empty) => continue,
Err(TryRecvError::Disconnected) => break,
}
}
// Or iterate (stops on disconnect)
for msg in rx {
handle(msg);
}
```
---
## Async Common Errors
### Forgetting to Spawn
```rust
// WRONG: future not polled
async fn fetch_data() -> Result<Data, Error> { ... }
fn process() {
fetch_data(); // does nothing! returns Future that's dropped
}
// RIGHT: await or spawn
async fn process() {
let data = fetch_data().await; // awaited
}
fn process_sync() {
tokio::spawn(fetch_data()); // spawned
}
```
### Blocking in Async Context
```rust
// WRONG: blocks the executor
async fn bad() {
std::thread::sleep(Duration::from_secs(1)); // blocks!
std::fs::read_to_string("file.txt").unwrap(); // blocks!
}
// RIGHT: use async versions
async fn good() {
tokio::time::sleep(Duration::from_secs(1)).await;
tokio::fs::read_to_string("file.txt").await.unwrap();
}
// Or spawn_blocking for CPU-bound work
async fn compute() {
let result = tokio::task::spawn_blocking(|| {
heavy_computation() // OK to block here
}).await.unwrap();
}
```
---
## Thread Panic Handling
### Unhandled Panic
```rust
let handle = std::thread::spawn(|| {
panic!("oops");
});
// Main thread continues, might miss the error
handle.join().unwrap(); // panics here
```
### Proper Error Handling
```rust
let handle = std::thread::spawn(|| {
panic!("oops");
});
match handle.join() {
Ok(result) => println!("Success: {:?}", result),
Err(e) => println!("Thread panicked: {:?}", e),
}
// For async: use catch_unwind
use std::panic;
async fn safe_task() {
let result = panic::catch_unwind(|| {
risky_operation()
});
match result {
Ok(v) => use_value(v),
Err(_) => log_error("task panicked"),
}
}
```