Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@B3rn475
Copy link
Contributor

@B3rn475 B3rn475 commented Jun 27, 2017

Trying to hot reload during debug freezes the system, due to the fact that WaitForPlatformViewIds tries to execute code on the main thread while it is locked, this in turn freezes the Service Isolate making impossible to continue debug or try to solve the situation.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jun 27, 2017

@jason-simmons
Copy link
Member

I don't think this will be safe.

platform_views_ was only accessed on the UI thread due to the thread safety rules of ftl::WeakPtr
(https://fuchsia.googlesource.com/ftl/+/master/memory/weak_ptr.h)

In particular, the code in Shell::WaitForPlatformViewIds that checks whether the PlatformView is still alive and then calls into the view's engine must only run on the UI thread.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jun 28, 2017

The WeakPtr are already not used in the same thread of the WeakPtrFactory.

They are created and accessed in the same thread, but they are potentially invalidated in other threads.

return PLATFORM_VIEW->Detach();

What is synchronized on destruction is the Purge, but not the actual delete.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jun 28, 2017

May moving from ftl::WeakPtr to std::weak_ptr solve the situation?

@jason-simmons
Copy link
Member

std::weak_ptr and std::shared_ptr have nicer thread safety properties than ftl::WeakPtr and might be worth trying.

You'll need to update all the supported platforms to hold the PlatformView in a shared_ptr instead of a raw pointer or unique_ptr. Also, if the end goal is to get information out of the Engine/RuntimeHolder on a thread other than the UI thread, then you'll need a safe way to do that. Engine is generally not safe to access outside the UI thread.

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jun 29, 2017

I will update all the other platforms ASAP.

For the thread safety of the Engine access I think that it is safe:

  • We have a shared_ptr that keeps a platform_view alive.
  • The platform_view has a unique_ptr that keeps alive a Engine object, it cannot be released.
  • The Engine has a unique_ptr that keeps alive a RuntimeController object, it cannot be released.
  • The RuntimeController has a unique_ptr that keeps alive a DartController object, it cannot be released.
  • The DartController has a raw pointer that keeps alive a UIDartState object, it cannot be released.
  • The UIDartState has direct access to the Dart_Port and to the debug_name that are both atomic values that cannot be changed from outside.

Copy link
Member

@jason-simmons jason-simmons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

std::vector<ftl::WeakPtr<PlatformView>> platform_views_;
std::vector<std::weak_ptr<PlatformView>> platform_views_;

std::recursive_mutex mutex_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename this platform_views_mutex_ to indicate what it guards

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, now i see that it's also being used to guard the rasterizers list. I'd suggest using two separate locks for platform_views and rasterizers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also. does this need to be a recursive_mutex, or can it be a plain std::mutex?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is needed otherwise the lock inside WaitForPlatformViewIds will acquire it and the nested invocation of GetPlatformViews will freeze.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WaitForPlatformViewIds can access platform_views_ directly while holding the mutex instead of calling GetPlatformViews. This will also avoid the list copy done by GetPlatformViews.

Copy link
Contributor Author

@B3rn475 B3rn475 Jul 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


#define PLATFORM_VIEW reinterpret_cast<PlatformViewAndroid*>(platform_view)
template <typename T>
class HeapSharedPtr {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of this wrapper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trough the JNI we can move just Java Objects or Atomic values.
The std::shared_ptr cannot be passed directly, but the std::make_shared method will create it on the stack.
We wrap it into an object in the heap that will be manually managed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the make_shared() call and the wrapper be replaced by new std::shared_ptr(new PlatformViewAndroid())?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

void PlatformViewAndroid::Detach() {
ReleaseSurface();
delete this;
//delete this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line before submitting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

void Shell::GetRasterizers(std::vector<ftl::WeakPtr<Rasterizer>>* rasterizers) {
FTL_DCHECK(gpu_thread_checker_ &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for the GPU thread was replaced by a mutex, but the pointers are still ftl::WeakPtrs that are bound to the GPU thread.

Is there a need to access the rasterizers list outside the GPU thread? If not, then I'd prefer to revert to using the GPU thread checker

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, it is an error, I will restore those thread based checks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

1 similar comment
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for the commit author(s). If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and have the pull request author add another comment and the bot will run again.

@googlebot
Copy link

CLAs look good, thanks!

1 similar comment
@googlebot
Copy link

CLAs look good, thanks!

@B3rn475
Copy link
Contributor Author

B3rn475 commented Jul 12, 2017

I've squashed all the commits to one

@jason-simmons jason-simmons merged commit 8ba522e into flutter:master Jul 12, 2017
@ianloic
Copy link
Contributor

ianloic commented Jul 12, 2017

This broke my build...

@ianloic
Copy link
Contributor

ianloic commented Jul 12, 2017

../../flutter/shell/testing/test_runner.cc:17:19: error: no member named 'Attach' in 'shell::PlatformView'
 platform_view_->Attach();
 ~~~~~~~~~~~~~~  ^

Looks like the test_runner host build broke.

B3rn475 added a commit that referenced this pull request Jul 19, 2017
In #3833 the `_flutter.listViews` RPC moved from thread based to lock based synchronization.
The thread based synchronization side effect was used by flutter benchmarks in https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/vmservice.dart#L1223 and
https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/run_hot.dart#L156 to ensure the completeness of the restart/reload and so correct timing.

A new RPC `_flutter.flushUIThreadTasks` is introduced to allow the flutter benchmarks to reintroduce thread based synchronization.

Related flutter/flutter#11241
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants