user1109: When a chess engine sees a position p repeated once (i.e. position p occurred twice) it immediately assigns the second occurrence of position p a draw score. This makes sense because position p doesn't need to occur thrice in order for the chess engine to realize that it's not making progress (i.e. a twofold repetition is just as drawn as a threefold repetition).
Many chess engines do just this. They assign a draw score to all twofold repetitions. However, some of the best chess engines such as Stockfish and Ethereal don't assign a draw score to all twofold repetitions. If the first occurrence of position p is not strictly after the root node then they don't assign a draw score to the twofold repetition. Instead, the position needs to be repeated twice (i.e. it needs to be a threefold repetition) in order for it to be assigned a draw score.
For example, consider the following drawnByRepetition function from the Ethereal source code:
int drawnByRepetition(Board *board, int height) {

    int reps = 0;

    // Look through hash histories for our moves
    for (int i = board->numMoves - 2; i >= 0; i -= 2) {

        // No draw can occur before a zeroing move
        if (i < board->numMoves - board->fiftyMoveRule)
            break;

        // Check for matching hash with a two fold after the root,
        // or a three fold which occurs in part before the root move
        if (    board->history[i] == board->hash
            && (i > board->numMoves - height || ++reps == 2))
            return 1;
    }

    return 0;
}

As you can see either i must be greater than the root node (i.e. it must come after the root node) or the position p needs to be repeated twice (i.e. it must be a threefold repetition) for it to be assigned a draw score.
The chess programming wiki has the following to say about assigning draw score to repetitions:

Threefold repetition implies a position occurred thrice, that is repeated twice. When to score the position as a draw, however, is an entirely different matter. Most programs do this on the first repetition, no matter whether the first occurrence of the repeated position appears in the current search space, or not. Other programs consider that fact, they avoid cycles inside the current search tree to make it a directed acyclic graph (DAG), but allow a one-fold repetition, if the first occurrence appears in the game history before the current root. Anyway, to wait for the second repetition one has its pros and cons. The Repetition score is either zero or the contempt factor.

It says that “to wait for the second repetition one has its pros and cons.” So, what exactly are the pros and cons? I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.

user825: 
It says that “to wait for the second repetition one has its pros and cons.” So, what exactly are the pros and cons? I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.

My discussion will be technical, so let's make it as simple as possible. Firstly, let's make be clear about this:

If the first occurrence of position p is not strictly after the root node then they don't assign a draw score to the twofold repetition.

Why would an engine do that? Let's consider two scenarios where we have three-fold repetition during the search. Let's assume we are on move 30th, and the engine is thinking at move 40th.

The position repeated and played on the board, for example, the position occurred on move 24th and 26th.
The position never actually played on the board, but it is part of the search. The position occurred at move 35th. (IMPORTANT - only a single repetition)

Scenario 1
In the first scenario, it's a repetition that we all understand. In your code example:
++reps == 2 

So, if a position repeated twice earlier in the game before the root (root == current board position), it's a three-fold repetition. Very simple.
Scenario 2
What about the second scenario? You have the identical position on move 35th, and the same position come back on move 40th. Thus, it's reasonable to assume if you search further you will encounter the position again (for the third repetition). For example, move 45th.
Your code example:
i > board->numMoves - height


So, what exactly are the pros and cons?

Pros: search quicker and deeper
Cons: you assume the same position would occur again later in the search (e.g. move 45th), which is not always true

I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.

Search quicker and deeper. Common optimization in modern chess programming.

1109: <p>When a chess engine sees a position <em>p</em> repeated once (i.e. position <em>p</em> occurred twice) it immediately assigns the second occurrence of position <em>p</em> a draw score. This makes sense because position <em>p</em> doesn't need to occur thrice in order for the chess engine to realize that it's not making progress (i.e. a twofold repetition is just as drawn as a threefold repetition).</p>

<p>Many chess engines do just this. They assign a draw score to all twofold repetitions. However, some of the best chess engines such as Stockfish and Ethereal don't assign a draw score to all twofold repetitions. If the first occurrence of position <em>p</em> is not strictly after the root node then they don't assign a draw score to the twofold repetition. Instead, the position needs to be repeated twice (i.e. it needs to be a threefold repetition) in order for it to be assigned a draw score.</p>

<p>For example, consider the following <a href="https://github.com/AndyGrant/Ethereal/blob/10a2c2f9cf2dfc0f4a3d172037bb6003bb1074e3/src/board.c#L316-L335" rel="nofollow noreferrer"><code>drawnByRepetition</code></a> function from the Ethereal source code:</p>



<pre><code>int drawnByRepetition(Board *board, int height) {

    int reps = 0;

    // Look through hash histories for our moves
    for (int i = board-&gt;numMoves - 2; i &gt;= 0; i -= 2) {

        // No draw can occur before a zeroing move
        if (i &lt; board-&gt;numMoves - board-&gt;fiftyMoveRule)
            break;

        // Check for matching hash with a two fold after the root,
        // or a three fold which occurs in part before the root move
        if (    board-&gt;history[i] == board-&gt;hash
            &amp;&amp; (i &gt; board-&gt;numMoves - height || ++reps == 2))
            return 1;
    }

    return 0;
}
</code></pre>

<p>As you can see either <code>i</code> must be greater than the root node (i.e. it must come after the root node) or the position <em>p</em> needs to be repeated twice (i.e. it must be a threefold repetition) for it to be assigned a draw score.</p>

<p>The chess programming wiki has the following to say about <a href="https://www.chessprogramming.org/Repetitions#Assigning_Draw_Score" rel="nofollow noreferrer">assigning draw score</a> to repetitions:</p>

<blockquote>
  <p>Threefold repetition implies a position occurred thrice, that is repeated twice. When to score the position as a draw, however, is an entirely different matter. Most programs do this on the first repetition, no matter whether the first occurrence of the repeated position appears in the current search space, or not. Other programs consider that fact, they avoid <a href="https://en.wikipedia.org/wiki/Cycle_%28graph_theory%29" rel="nofollow noreferrer">cycles</a> inside the current <a href="https://www.chessprogramming.org/Search_Tree" rel="nofollow noreferrer">search tree</a> to make it a <a href="https://en.wikipedia.org/wiki/Directed_acyclic_graph" rel="nofollow noreferrer">directed acyclic graph</a> (DAG), but allow a one-fold repetition, if the first occurrence appears in the game history before the current <a href="https://www.chessprogramming.org/Root" rel="nofollow noreferrer">root</a>. Anyway, to wait for the second repetition one has its pros and cons. The Repetition score is either zero or the <a href="https://www.chessprogramming.org/Contempt_Factor" rel="nofollow noreferrer">contempt factor</a>.</p>
</blockquote>

<p>It says that &ldquo;to wait for the second repetition one has its pros and cons.&rdquo; So, what exactly are the pros and cons? I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.</p>
 825: <blockquote>
  <p>It says that “to wait for the second repetition one has its pros and cons.” So, what exactly are the pros and cons? I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.</p>
</blockquote>

<p>My discussion will be technical, so let's make it as simple as possible. Firstly, let's make be clear about this:</p>

<blockquote>
  <p>If the first occurrence of position p is not strictly after the root node then they don't assign a draw score to the twofold repetition.</p>
</blockquote>

<p>Why would an engine do that? Let's consider <strong>two scenarios</strong> where we have three-fold repetition during the search. Let's assume we are on move 30th, and the engine is thinking at move 40th.</p>

<ul>
<li>The position repeated and played on the board, for example, the position occurred on move 24th and 26th.</li>
<li>The position <strong>never</strong> actually played on the board, but it is part of the search. The position occurred at move 35th. (IMPORTANT - only a single repetition)</li>
</ul>

<p><strong>Scenario 1</strong></p>

<p>In the first scenario, it's a repetition that we all understand. In your code example:</p>

<pre><code>++reps == 2 
</code></pre>

<p>So, if a position repeated twice earlier in the game <strong>before</strong> the root (root == current board position), it's a three-fold repetition. Very simple.</p>

<p><strong>Scenario 2</strong></p>

<p>What about the second scenario? You have the identical position on move 35th, and the same position come back on move 40th. Thus, it's reasonable to assume if you search further you will encounter the position again (for the third repetition). For example, move 45th.</p>

<p>Your code example:</p>

<pre><code>i &gt; board-&gt;numMoves - height
</code></pre>

<blockquote>
  <p>So, what exactly are the pros and cons?</p>
</blockquote>

<p>Pros: search quicker and deeper</p>

<p>Cons: you assume the same position would occur again later in the search (e.g. move 45th), which is not always true</p>

<blockquote>
  <p>I couldn't find an explanation as to why top chess engines like Stockfish and Ethereal do this.</p>
</blockquote>

<p>Search quicker and deeper. Common optimization in modern chess programming.</p>
