Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Dec 30, 2019

This flag was causing issues when accessing console properties on concurrent threads during TermInfoDriver initialisation.

Fixes #18317

@ghost ghost requested review from akoeplinger and steveisok as code owners December 30, 2019 08:42
@lambdageek
Copy link
Member

approve

@dnfclas
Copy link

dnfclas commented Dec 31, 2019

CLA assistant check
All CLA requirements met.

@jaykrell
Copy link
Contributor

Looks racy -- more on-demand initialization, and without data dependency..

@jaykrell
Copy link
Contributor

Generic fix is to put all the state behind one pointer, that goes from null to non-null, once.

@lambdageek
Copy link
Member

@jaykrell how is it racy? it's behind a lock...

@jaykrell
Copy link
Contributor

jaykrell commented Dec 31, 2019

  1. Why is try/finally preferred? Do you want retry upon failure, or sticky failure, and is failure well handled either way? Try/finally makes failure sticky. I should read the code more.

  2. The reads are not behind a lock?

if (inited)
{
  use foo;
}
else
{
  lock
  {
     foo = …
     inited = true
  }

is racy if foo is not a pointer (or the use does not dereference, such as compare to null or print).

@ghost
Copy link
Author

ghost commented Dec 31, 2019

  1. Why is try/finally preferred? Do you want retry upon failure, or sticky failure, and is failure well handled either way? Try/finally makes failure sticky. I should read the code more.

In the original code, an exception on initialisation may fail to fully initialise, but will leave the class in an initialised state (since inited = true will always be set). After I've moved the inited = true statement to the end of the block, the addition of try/finally retains that behaviour.

  1. The reads are not behind a lock?

From what I can see, all reads and writes to the uninitialised class will be gated at the lock until the class is initialised. After inited = true, the lock is not considered for any further operations, so it's a transient gate and is almost insignificantly short lived. I admit there's some racy-ness here, but all of it would have existed before my changes.

I did consider refactoring the class, but I think that would be a separate issue given the greater surface area.

@steveisok
Copy link
Contributor

I think it's fine for the issue @nagytech is trying to solve. I agree that refactoring is a separate effort.

@jaykrell
Copy link
Contributor

jaykrell commented Dec 31, 2019

The code is racy, and fails as a result, and the fix is to keep it racy, just less so? Is that right?

@ghost
Copy link
Author

ghost commented Dec 31, 2019

@jaykrell

The code is racy, and fails as a result, and the fix is to keep it racy, just less so? Is that right?

In general, yes. But, more specifically I would say that there are two distinct behaviours here:

  1. The initialisation of TermInfoDriver is racy, and fails as a result, and the fix is to remove the racy aspect of the initialisation - which I've done; and

  2. The post-initialized behaviour of TermInfoDriver is racy, and the fix would be best dealt with separately.

@steveisok
Copy link
Contributor

@monojenkins build failed

@steveisok steveisok merged commit 5470386 into mono:master Jan 2, 2020
@steveisok
Copy link
Contributor

@monojenkins backport 2019-12

monojenkins added a commit that referenced this pull request Jan 3, 2020
…etes (#18329)

[2019-12] Set inited flag _after_ TermInfoDriver initialisation completes

This flag was causing issues when accessing console properties on concurrent threads during TermInfoDriver initialisation.

Fixes #18317

Backport of #18318.

/cc @steveisok @nagytech
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.

DivideByZeroException with concurrent initialisation of TermInfoDriver

5 participants