Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix MonitorChild thread violation in utility process #8620

Merged
merged 5 commits into from
Apr 30, 2021

Conversation

darkdh
Copy link
Member

@darkdh darkdh commented Apr 23, 2021

Resolves brave/brave-browser#15235

MonitorChild is no longer a member function but still running on child monitor thread, and it will run callback in the original thread using BindPostTask.
We cannot bind crash_handler_callback_ directly in BindPostTask because we need to access some members in OnChildCrash and the callback must be called before it is destructed otherwise we will hit this DCHECK

  static void OnIsConnectedComplete(bool connected) {
    DCHECK(!connected)
        << "TorLauncher::LaunchCallback was destroyed without "
        << "first either being run or its corresponding binding being closed. "
        << "It is an error to drop response callbacks which still correspond "
        << "to an open interface pipe.";
  }

Also introduce ChildProcessMonitor to deduplicate the external child lifetime monitoring logic

Submitter Checklist:

  • I confirm that no security/privacy review is needed, or that I have requested one
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally: npm run test -- brave_browser_tests, npm run test -- brave_unit_tests, npm run lint, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

@darkdh darkdh self-assigned this Apr 23, 2021
@darkdh darkdh force-pushed the utility-monitor-child branch 2 times, most recently from 1499f09 to 9895a95 Compare April 23, 2021 05:38
DISALLOW_COPY_AND_ASSIGN(IpfsServiceImpl);
base::WeakPtrFactory<IpfsServiceImpl> weak_ptr_factory_{this};

IpfsServiceImpl(const IpfsServiceImpl&) = delete;
Copy link
Member

Choose a reason for hiding this comment

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

methods/constructors should go before members.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 7757acb

} else if (WIFEXITED(status)) {
VLOG(0) << "ipfs exit (" << WEXITSTATUS(status) << ")";
}
if (callback) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe just DCHECK(callback); at start and remove ifs? it's unlikely someone would use it without a callback.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 7757acb

@@ -108,22 +109,62 @@ bool LaunchProcessAndExit(const base::FilePath& path,
return true;
}

void MonitorChild(base::ProcessHandle p_handle,
Copy link
Member

Choose a reason for hiding this comment

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

can we put this machinery in a dedicated .h/.cc and fix code duplication? ipfs/tor impls clearly cannot be used simultaneously because of global sigaction calls.
it would be nice to have a single entry point for the Setup/TearDownPipeHack, MonitorChild and DCHECK if it's used in the same process for something else.

Copy link
Member Author

Choose a reason for hiding this comment

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

I will fix the duplication by wrapping a ChildMonitor class and also global sigaction calls don't matter because IpfsServiceImpl and TorLauncherImpl are in different utility processes.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 7757acb

@darkdh darkdh force-pushed the utility-monitor-child branch 3 times, most recently from 7757acb to d74ac50 Compare April 26, 2021 23:16
components/external_child_process/child_monitor.cc Outdated Show resolved Hide resolved
components/external_child_process/child_monitor.cc Outdated Show resolved Hide resolved
memset(&action, 0, sizeof(action));
action.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &action, NULL);
for (size_t i = 0; i < 2; ++i)
Copy link
Contributor

Choose a reason for hiding this comment

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

since there will only ever be two pipe elements a loop doesn't add much.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in fcf4957f689f39e8f09a0c9aa56494935fcbfd7d

@@ -0,0 +1,13 @@
source_set("child_monitor") {
Copy link
Member

Choose a reason for hiding this comment

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

components/child_process_monitor/BUILD.gn
source_set("child_process_monitor") { ... }?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

@@ -0,0 +1,13 @@
source_set("child_monitor") {
visibility = [
"//brave/components/services/ipfs",
Copy link
Member

Choose a reason for hiding this comment

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

maybe add a comment why we restrict visibility?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

NOTREACHED();
}
}
ChildMonitor::~ChildMonitor() {
Copy link
Member

Choose a reason for hiding this comment

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

an empty line is missing

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

<< ")";
}
std::move(callback).Run(pid);
}
Copy link
Member

Choose a reason for hiding this comment

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

break; / return; to be safe?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

} // namespace

ChildMonitor::ChildMonitor()
: child_monitor_thread_(new base::Thread("child_monitor_thread")) {
Copy link
Member

Choose a reason for hiding this comment

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

std::make_unique

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
child_process_ = std::move(child);

DCHECK(child_monitor_thread_.get());
Copy link
Member

Choose a reason for hiding this comment

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

just DCHECK(child_monitor_thread_);

#include "base/process/kill.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
Copy link
Member

Choose a reason for hiding this comment

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

sequenced_task_runner_handle.h

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

}

#if defined(OS_MAC)
static void SetupFD(int fd) {
Copy link
Member

Choose a reason for hiding this comment

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

static void SIGCHLDHandler
static void SetupFD
static void SetupPipeHack
static void TearDownPipeHack

static is not necessary. we're already in anonymous namespace.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

// processes created above.
SetupPipeHack();
#endif
child_monitor_.reset(new brave::ChildMonitor());
Copy link
Member

Choose a reason for hiding this comment

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

std::make_unique

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

#if defined(OS_MAC)
// TODO(https://crbug.com/806451): The Mac implementation currently blocks
// the calling thread for up to two seconds.
base::PostTask(
Copy link
Member

Choose a reason for hiding this comment

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

base::ThreadPool::PostTask

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 76857501ecbfb2f31ff1023ec197de6d90d62618

@darkdh darkdh force-pushed the utility-monitor-child branch 5 times, most recently from cff041b to 1db72ee Compare April 28, 2021 19:15
@darkdh darkdh requested review from goodov and kkuehlz April 28, 2021 23:40
if (fcntl(pipehack[1], F_SETFL, flags) == -1)
VLOG(0) << "set flags errno:" << errno;

struct sigaction action;
Copy link
Contributor

Choose a reason for hiding this comment

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

generally it's a good idea to set SA_RESTART in your sigaction flags, especially since your code is doing a lot of syscalls.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed in 2ce89fab2bc58cb8ab04ef80cb0f2efaaa56cbbe

Copy link
Contributor

@kkuehlz kkuehlz left a comment

Choose a reason for hiding this comment

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

LGTM

@darkdh
Copy link
Member Author

darkdh commented Apr 30, 2021

11:26:46  1 test crashed:
11:26:46      RewardsContributionBrowserTest.AutoContributionMultiplePublishersUphold (../../brave/components/brave_rewards/browser/test/rewards_contribution_browsertest.cc:214)

not related to this PR
https://ci.brave.com/job/pr-brave-browser-utility-monitor-child-linux/16/execution/node/221/log/

@darkdh darkdh merged commit eb4d020 into master Apr 30, 2021
@darkdh darkdh deleted the utility-monitor-child branch April 30, 2021 23:39
@darkdh darkdh added this to the 1.26.x - Nightly milestone Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix base::Unretained/thread issues in MonitorChild usages
3 participants