Clarify File::lock docs are cross-process#153652
Clarify File::lock docs are cross-process#153652VedantMadane wants to merge 1 commit intorust-lang:mainfrom
Conversation
|
rustbot has assigned @Mark-Simulacrum. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
|
The job Click to see the possible cause of the failure (guessed by this bot)For more information how to resolve CI failures of this job, visit this link. |
|
Something seems to have broken very badly with this commit, the entire file is being marked as changed (maybe line ending problems?) and several lines are missing from the end of the file. |
There was a problem hiding this comment.
This is a 6,900 line diff for a ~8-line doc change. The file appears to have been regenerated by a tool.
| /// ```no_run | ||
| /// use std::fs; | ||
| /// | ||
| /// fn main() -> Result<(), Box ) -> fmt::Result { | ||
| match self { | ||
| TryLockError::Error(err) => err.fmt(f), | ||
| TryLockError::WouldBlock => "WouldBlock".fmt(f), | ||
| } | ||
| } |
| /// | ||
| /// let path = "/tmp/foo/bar/baz"; | ||
| /// DirBuilder::new() | ||
| /// .recursive(true) | ||
| /// .create(path).unwrap(); | ||
| /// | ||
| /// assert!(fs::metadata(path).unwrap().is_dir()); | ||
| /// ``` | ||
| #[stable(feature = "dir_builder", since = "1.6.0")] | ||
| pub fn create >(&self, path: P) -> io::Result<()> { | ||
| self._create(path.as_ref()) | ||
| } | ||
|
|
||
| fn _create(&self, path: &Path) -> io::Result<()> { | ||
| if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) } | ||
| } | ||
|
|
||
| fn create_dir_all(&self, path: &Path) -> io::Result<()> { | ||
| // if path's parent is None, it is "/" path, which should | ||
| // return Ok immediately | ||
| if path == Path::new("") || path.parent() == None { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let ancestors = path.ancestors(); | ||
| let mut uncreated_dirs = 0; | ||
|
|
||
| for ancestor in ancestors { | ||
| // for relative paths like "foo/bar", the parent of | ||
| // "foo" will be "" which there's no need to invoke | ||
| // a mkdir syscall on | ||
| if ancestor == Path::new("") || ancestor.parent() == None { | ||
| break; | ||
| } | ||
|
|
||
| match self.inner.mkdir(ancestor) { | ||
| Ok(()) => break, | ||
| Err(e) if e.kind() == io::ErrorKind::NotFound => uncreated_dirs += 1, | ||
| // we check if the err is AlreadyExists for two reasons | ||
| // - in case the path exists as a *file* | ||
| // - and to avoid calls to .is_dir() in case of other errs | ||
| // (i.e. PermissionDenied) | ||
| Err(e) if e.kind() == io::ErrorKind::AlreadyExists && ancestor.is_dir() => break, | ||
| Err(e) => return Err(e), | ||
| } | ||
| } | ||
|
|
||
| // collect only the uncreated directories w/o letting the vec resize | ||
| let mut uncreated_dirs_vec = Vec::with_capacity(uncreated_dirs); | ||
| uncreated_dirs_vec.extend(ancestors.take(uncreated_dirs)); | ||
|
|
||
| for uncreated_dir in uncreated_dirs_vec.iter().rev() { | ||
| if let Err(e) = self.inner.mkdir(uncreated_dir) { | ||
| if e.kind() != io::ErrorKind::AlreadyExists || !uncreated_dir.is_dir() { | ||
| return Err(e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| impl AsInnerMut for DirBuilder { | ||
| #[inline] | ||
| fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder { | ||
| &mut self.inner | ||
| } | ||
| } | ||
|
|
||
| /// Returns `Ok(true)` if the path points at an existing entity. | ||
| /// | ||
| /// This function will traverse symbolic links to query information about the | ||
| /// destination file. In case of broken symbolic links this will return `Ok(false)`. | ||
| /// | ||
| /// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)` | ||
| /// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed | ||
| /// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing | ||
| /// permission is denied on one of the parent directories. | ||
| /// | ||
| /// Note that while this avoids some pitfalls of the `exists()` method, it still can not | ||
| /// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios | ||
| /// where those bugs are not an issue. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```no_run | ||
| /// use std::fs; | ||
| /// | ||
| /// assert!(!fs::exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt")); | ||
| /// assert!(fs::exists("/root/secret_file.txt").is_err()); | ||
| /// ``` | ||
| /// | ||
| /// [`Path::exists`]: crate::path::Path::exists | ||
| /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou | ||
| #[stable(feature = "fs_try_exists", since = "1.81.0")] | ||
| #[inline] | ||
| pub fn exists >(path: P) -> io::Result { | ||
| fs_imp::exists(path.as_ref()) | ||
| } |
There was a problem hiding this comment.
looks like the file was regenerated by an LLM...
the entire file is replaced in a single hunk, a lot of impls and attributes are gone, and the structure is corrupted. This does not compile.
|
Hello @VedantMadane, When contributing, please check if there's someone assigned to the issue or if a PR has been posted. Close as duplicate of #153647 |
Fixes #153618
The current documentation doesn't mention that these locks work across processes. This PR adds explicit clarification that the locks are advisory and work across processes: when one process holds a lock, other processes opening the same file will block or fail when trying to acquire a conflicting lock.
Updated documentation for:
locklock_sharedtry_locktry_lock_sharedunlock(added cross-reference to lock methods)