Repository: denoland/deno
File: resolvers/npm_installer/flag.rs (Rust)

Code before:
                      ));
                    }
                  }
                });

                return Self(Some(LaxSingleProcessFsFlagInner {
                  file_path,
                  fs_file,
                  finished_flag,
                }));
              }
              Err(_) => {
                // show a message if it's been a while
                if pb_update_guard.is_none()
                  && start_instant.elapsed().as_millis() > 1_000
                {
                  let guard = reporter.on_blocking(long_wait_message);
                  pb_update_guard = Some(guard);
                }

                // sleep for a little bit
                tokio::time::sleep(Duration::from_millis(20)).await;

                // Poll the last updated path to check if it's stopped updating,
                // which is an indication that the file lock is claimed, but
                // was never properly released.
                match sys
                  .fs_metadata(&last_updated_path)
                  .and_then(|p| p.modified())
                {
                  Ok(last_updated_time) => {
                    let current_time = sys.sys_time_now();
                    match current_time.duration_since(last_updated_time) {
                      Ok(duration) => {
                        if duration.as_millis()
                          > (poll_file_update_ms * 2) as u128
                        {
                          // the other process hasn't updated this file in a long time
                          // so maybe it was killed and the operating system hasn't
                          // released the file lock yet
                          return Self(None);
                        } else {
                          error_count = 0; // reset
                        }
                      }
                      Err(_) => {
                        error_count += 1;
                      }
                    }
                  }
                  Err(_) => {

Review comment (suggestion):
I kind of feel like we should be using a conditional variable here in order to kill the thread more quickly in case this is hanging shutdown, but this is probably fine.

Code after:
            let lock_result =
              fs_file.fs_file_try_lock(sys_traits::FsFileLockMode::Exclusive);
            let poll_file_update_ms = 100;
            match lock_result {
              Ok(_) => {
                log::debug!("Acquired file lock at {}", file_path.display());
                let mut poll_file =
                  PollFile::new(sys.clone(), last_updated_path);
                poll_file.touch();
                let poll_file = Arc::new(Mutex::new(Some(poll_file)));

                // Spawn a blocking task that will continually update a file
                // signalling the lock is alive. This is a fail safe for when
                // a file lock is never released. For example, on some operating
                // systems, if a process does not release the lock (say it's
                // killed), then the OS may release it at an indeterminate time
                //
                // This uses a blocking task because we use a single threaded
                // runtime and this is time sensitive so we don't want it to update
                // at the whims of whatever is occurring on the runtime thread.
                let sys = sys.clone();
                deno_unsync::spawn_blocking({
                  let poll_file = poll_file.clone();
                  move || loop {
                    sys
                      .thread_sleep(Duration::from_millis(poll_file_update_ms));
                    match &mut *poll_file.lock() {
                      Some(poll_file) => poll_file.touch(),
                      None => return,
                    }
                  }
                });

                return Self(Some(LaxSingleProcessFsFlagInner {
                  file_path,
                  fs_file,
                  poll_file,
                }));
              }
              Err(_) => {
                // show a message if it's been a while
                if pb_update_guard.is_none()
                  && start_instant.elapsed().as_millis() > 1_000
                {
                  let guard = reporter.on_blocking(long_wait_message);
                  pb_update_guard = Some(guard);
                }

                // sleep for a little bit
                tokio::time::sleep(Duration::from_millis(20)).await;