Function marked as blocking was called from a scope that disallows blocking

445 views
Skip to first unread message

Lucas Radaelli

unread,
Oct 6, 2023, 5:44:39 PM10/6/23
to schedu...@chromium.org
I am following the guidance from this doc to try to get some help.

I have a change (WIP here), where I am trying to open a file and return it through a mojo callback. When posting a task to open the file through a ThreadPool, some part of my code is marking my code as blocking even after adding task traits to indicate that this operation MayBlock. Sample run output here with the full error.

Relevant code part:
void AccessibilityServiceClient::Load(const base::FilePath& path,
                                      LoadCallback callback) {
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()}, base::BindOnce(&LoadFile, path),
      base::BindOnce(&OnFileLoaded, std::move(callback)));
}



Where LoadFile is implemented as:
base::File LoadFile(base::FilePath path) {
  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  base::FilePath resources_path;
  if (!base::PathService::Get(chrome::DIR_RESOURCES, &resources_path)) {
    NOTREACHED();
  }

  base::FilePath accessibility_file_path =
      resources_path.Append(extension_misc::kAccessibilityCommonExtensionPath)
          .Append(path);
  LOG(INFO) << accessibility_file_path.MaybeAsASCII();
  base::File file(accessibility_file_path,
                  base::File::FLAG_OPEN | base::File::FLAG_READ);
  return file;
}

And OnFileLoaded is implemented as:
void OnFileLoaded(
    AccessibilityServiceClient::LoadCallback callback,
    base::File file) {
  std::move(callback).Run(std::move(file));
}


Where:
- To open a file I am posting the task to the ThreadPool, and marking through traits that this may block;
- Callback must run in the same sequence in which the mojo InterfacePtr is bound (that's why it is passed to the on result parameter of PostTask above);
- So the base::File is the result of the task run.

I suspect that the presence of the base::File in the function signature for OnFileLoaded is causing the scheduler to think that the second function may block, although I am just trying to run the callback sending the resultt (which is the file already opened).

I tried to use base::ScopedAllowBlocking in the function body of OnFileLoaded with no success.

I ran out of ideas of what could be, so I am asking for help.

Thanks.





Lucas Radaelli

unread,
Oct 9, 2023, 2:38:09 PM10/9/23
to schedu...@chromium.org
Also, if there is a more appropriate forum to ask this, please let me know.

Daniel Cheng

unread,
Oct 9, 2023, 2:56:58 PM10/9/23
to Lucas Radaelli, schedu...@chromium.org, Chromium-dev
The stack trace looks a bit wonky:

#0 0x55fc9c7fd3a2 base::debug::CollectStackTrace()
#1 0x55fc9c7e25f3 base::debug::StackTrace::StackTrace()
#2 0x55fc9c6df2ab logging::LogMessage::~LogMessage()
#3 0x55fc9c6c3e10 logging::(anonymous namespace)::DCheckLogMessage::~DCheckLogMessage()
#4 0x55fc9c6c3c57 logging::CheckError::~CheckError()
#5 0x55fc9c7b98f1 base::internal::AssertBlockingAllowed()
#6 0x55fc9c7b138d base::ScopedBlockingCall::ScopedBlockingCall()
#7 0x55fc9c7cc825 base::File::Close()
#8 0x55fc9c6cf58e base::File::~File()
#9 0x55fc95aa9ea9 base::internal::BindLambdaHelper<>::Run()
#10 0x55fc95aa9ee1 base::internal::Invoker<>::Run()
#11 0x55fc9425938c base::OnceCallback<>::Run()
#12 0x55fc9b9bb6d4 ax::mojom::AccessibilityFileLoader_Load_ForwardToCallback::Accept()

As it really looks like it's happening in the caller when calling PostTaskAndReplyWithResult().

However, I think the underlying problem is that closing a valid base::File is *also* considered a blocking operation, though I don't have good recommendations for the best way to handle this. Maybe someone on chromium-dev (CCed here) will have some thoughts or has seen something similar before.

--
You received this message because you are subscribed to the Google Groups "scheduler-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-de...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/scheduler-dev/CAEhCMOyYR3yFXyvcNsZhV51YygpHmxaa98q5Vbv2C_1kuQPQ%2BQ%40mail.gmail.com.

Chris Fredrickson

unread,
Oct 9, 2023, 3:08:48 PM10/9/23
to Chromium-dev, Daniel Cheng, schedu...@chromium.org, Chromium-dev, Lucas Radaelli
I didn't look through the whole CL, but I can confirm that ~base::File is also considered blocking if the File is valid. In a project I worked on, we handled this by posting to the threadpool again to run the dtor when we needed to. I'm not sure if there's a better way.

To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-dev+unsubscribe@chromium.org.

Lucas Radaelli

unread,
Oct 9, 2023, 3:44:14 PM10/9/23
to Chris Fredrickson, Chromium-dev, Daniel Cheng, schedu...@chromium.org
In my case, I am not calling the destructor, but rather moving the base::File into a callback that is the reply value of a mojo call.

Because the callback of a mojo reply needs to be invoked in the same sequence in which the InterfacePTR is bound, I can't move the callback to the thread pool and call it.

Does it mean that with these restrictions I can't have a base::File as the return value of a mojo method?



To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-de...@chromium.org.

Lucas Radaelli

unread,
Oct 9, 2023, 4:02:51 PM10/9/23
to Chris Fredrickson, Chromium-dev, Daniel Cheng, schedu...@chromium.org
In my case, I am not calling the destructor, but rather moving the base::File into a callback that is the reply value of a mojo call.

Because the callback of a mojo reply needs to be invoked in the same sequence in which the InterfacePTR is bound, I can't move the callback to the thread pool and call it.

Does it mean that with these restrictions I can't have a base::File as the return value of a mojo method?

On Mon, Oct 9, 2023 at 12:08 PM Chris Fredrickson <cfre...@chromium.org> wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-de...@chromium.org.

Matthew Denton

unread,
Oct 10, 2023, 5:43:12 PM10/10/23
to Chromium-dev, Joe Mason, Chris Fredrickson, Chromium-dev, Daniel Cheng, schedu...@chromium.org, Lucas Radaelli
Right now your AccessibilityFileLoader runs on the UI thread and then posts the actual LoadFile task to a thread pool. Instead you can just bind your AccessibilityFileLoader on a thread pool sequence directly and avoid an extra hop, it should also solve this blocking problem.

I'm actuall surprised the base::File can't be used as a return value, the File should no longer be valid after being serialized and so the destructor shouldn't enter a blocking scope. Not sure what's going on there.

On Tuesday, October 10, 2023 at 2:35:44 PM UTC-7 Joe Mason wrote:
I haven't looked closely at the problem or code, so this suggestion might be off-base, but: you could return a base::SequenceBound wrapper of the base::File, which will automatically call the destructor on the right sequence after the callback drops it.
To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-dev+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "scheduler-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-dev+unsubscribe@chromium.org.

Matthew Denton

unread,
Oct 10, 2023, 5:54:25 PM10/10/23
to Chromium-dev, Matthew Denton, Joe Mason, Chris Fredrickson, Chromium-dev, Daniel Cheng, schedu...@chromium.org, Lucas Radaelli
Ah I read the output from the sample run--the blocking call does not come from running a mojo callback, instead the blocking ~File call is in the AccessibilityServiceAsksClientToLoadAFile test. It's the base::BindLambdaForTesting.

Lucas Radaelli

unread,
Oct 11, 2023, 5:21:16 PM10/11/23
to Matthew Denton, Chromium-dev, Joe Mason, Chris Fredrickson, Daniel Cheng, schedu...@chromium.org
Just to close the loop, that was it!

The destructor of the base::File, inside the test, which runs in a single process, is marked as blocking. Operations can't be blocking here (even inside a test), so the destructor of the base::File must be called inside a task in the thread pool.

I was reading incorrectly the stack trace (but fair enough this could be a bit more readable), and thought the problem was in the browser.

For the reference this is how I fixed the test:

base::RunLoop loop;
  fake_service_->LoadFile(
      base::FilePath(extension_misc::kChromeVoxManifestFilename),
      base::BindLambdaForTesting([&loop](base::File file) mutable {
        base::ThreadPool::PostTaskAndReplyWithResult(
            FROM_HERE, {base::MayBlock()},
            base::BindLambdaForTesting(
                [file = std::move(file)]() { return file.IsValid(); }),
            base::BindLambdaForTesting(
                [quit_closure = loop.QuitClosure()](bool result) {
                  ASSERT_TRUE(result);
                  std::move(quit_closure).Run();
                }));
      }));
  loop.Run();

Thanks all for the help.




To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-de...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "scheduler-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scheduler-de...@chromium.org.

Reilly Grant

unread,
Oct 12, 2023, 2:04:49 PM10/12/23
to lucasr...@google.com, Matthew Denton, Chromium-dev, Joe Mason, Chris Fredrickson, Daniel Cheng, schedu...@chromium.org
You can also use base::ScopedAllowBlockingForTesting to disable this requirement in test code, but be careful to narrowly scope it so that you aren't accidentally disabling a check that would fail in production.
Reilly Grant | Software Engineer | rei...@chromium.org | Google Chrome


--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-dev/CAEhCMOwP1BivKqM1XFqvgw%3DHfG5wjRfPP_kWGkdUZmEEpWj6Ug%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages