Skip to content

Commit e5f1ae9

Browse files
author
David Koloski
committed
Add set_max_level_racy and gate set_max_level
Calling `set_max_level` can result in a race condition on platforms that don't have an atomic compare and swap implementation. This gates `set_max_level` behind `#[cfg(atomic_cas)]` and adds a racy alternative that can be called in these situations. This mirrors the approach for `set_logger`.
1 parent dc32ab9 commit e5f1ae9

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/lib.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1215,10 +1215,38 @@ where
12151215
///
12161216
/// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs.
12171217
#[inline]
1218+
#[cfg(atomic_cas)]
12181219
pub fn set_max_level(level: LevelFilter) {
12191220
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
12201221
}
12211222

1223+
/// A thread-unsafe version of [`set_max_level`].
1224+
///
1225+
/// This function is available on all platforms, even those that do not have
1226+
/// support for atomics that is needed by [`set_max_level`].
1227+
///
1228+
/// In almost all cases, [`set_max_level`] should be preferred.
1229+
///
1230+
/// # Safety
1231+
///
1232+
/// This function is only safe to call when no other level setting function is
1233+
/// called while this function still executes.
1234+
///
1235+
/// This can be upheld by (for example) making sure that **there are no other
1236+
/// threads**, and (on embedded) that **interrupts are disabled**.
1237+
///
1238+
/// Is is safe to use all other logging functions while this function runs
1239+
/// (including all logging macros).
1240+
///
1241+
/// [`set_max_level`]: fn.set_max_level.html
1242+
#[inline]
1243+
pub unsafe fn set_max_level_racy(level: LevelFilter) {
1244+
// `MAX_LOG_LEVEL_FILTER` uses a `Cell` as the underlying primitive when a
1245+
// platform doesn't support `atomic_cas`, so even though this looks the same
1246+
// as `set_max_level` it may have different safety properties.
1247+
MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
1248+
}
1249+
12221250
/// Returns the current maximum log level.
12231251
///
12241252
/// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check

0 commit comments

Comments
 (0)