<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/55001>55001</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            lldb: process/runlock state mismatch in remote process launch codepath; gives error: invalid thread
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          dmlary
      </td>
    </tr>
</table>

<pre>
    ## Overview
When using `process launch --stop-at-entry` on a remote host, lldb (v13.0.1) does not correctly set the selected thread when the inferior process is launched.  As a result, many commands (`step-inst`, `read registers`, etc) output `error: invalid thread`, and do not function.

Example:
```txt
# on remote linux system
lldb-server p --server --listen "*:2323"

# on local system
(lldb) platform select remote-linux
  Platform: remote-linux
 Connected: no
(lldb) platform connect connect://remote-host:2323
  Platform: remote-linux
    Triple: x86_64-unknown-linux-gnu
OS Version: 3.10.0 (3.10.0-1127.el7.x86_64)
  Hostname: remote-host
 Connected: yes
WorkingDir: /home/user
    Kernel: #1 SMP Tue Feb 18 16:39:12 EST 2020
(lldb) file ./hello
Current executable set to '/Users/user/src/hello' (x86_64).
(lldb) process launch --stop-at-entry
Process 14578 launched: '/Users/user/src/hello' (x86_64)
(lldb) th list
Process 14578 stopped
* thread #1: tid = 14578, 0x00007ffff7ddc140 ld-2.17.so`_start, name = 'hello', stop reason = signal SIGSTOP
(lldb) reg r
error: invalid thread
(lldb) si
error: invalid thread
(lldb) thread select 1
* thread #1, name = 'hello', stop reason = signal SIGSTOP
    frame #0: 0x00007ffff7ddc140 ld-2.17.so`_start
ld-2.17.so`_start:
->  0x7ffff7ddc140 <+0>: movq   %rsp, %rdi
    0x7ffff7ddc143 <+3>: callq  0x7ffff7ddc850            ; _dl_start

ld-2.17.so`_dl_start_user:
    0x7ffff7ddc148 <+0>: movq   %rax, %r12
    0x7ffff7ddc14b <+3>: movl   0x220c37(%rip), %eax      ; _dl_skip_args
(lldb) si
error: invalid thread
```

## State mismatch between Process state & Process RunLock state
The source of the `error: invalid thread` error is `CommandObject::CheckRequirements()` when `m_thread_sp` is null on the `ExecutionContext` for the `CommandInterpreter`.  That `ExecutionContext` is created from an `ExecutionContextRef` that is setup using `ExecutionContextRef::SetTargetPtr()`.

In `ExecutionContextRef::SetTargetPtr()`, `process_sp->GetState()` is correctly set to `eStateStopped`, but the RunLock thinks the process is still running (`process_sp->GetRunlock().m_running == true`).  As a result, `SetTargetPtr()` will not set the `m_thread_sp`, because it believes the process is running.
```txt
frame #2: 0x00007f4e4be4debd liblldb.so.13`lldb_private::ExecutionContextRef::SetTargetPtr(this=0x00007ffc5b1dfd10, target=0x00000000019b8620, adopt_selected=true) at ExecutionContext.cpp:517:36
   514              // resuming.
   515              Process::StopLocker stop_locker;
   516
-> 517                   if (stop_locker.TryLock(&process_sp->GetRunLock()) &&
   518                  StateIsStoppedState(process_sp->GetState(), true)) {
   519                lldb::ThreadSP thread_sp(
   520                    process_sp->GetThreadList().GetSelectedThread());
(lldb) p process_sp->GetState()
(lldb::StateType) $43 = eStateStopped
(lldb) p process_sp->GetRunLock()
(lldb_private::ProcessRunLock) $44 = {
  m_rwlock = {
    __data = {
      __lock = 0
      __nr_readers = 1
      __readers_wakeup = 0
      __writer_wakeup = 0
      __nr_readers_queued = 0
      __nr_writers_queued = 0
      __writer = 0
      __shared = 0
      __pad1 = 0
      __pad2 = 0
      __flags = 0
    }
    __size = ""
    __align = 4294967296
  }
  m_running = true
}
```

## Possible cause
So it looks like `Process::SetPublicState()` is responsible for keeping the Process state & Process RunLock state in sync, but it will only update the RunLock state if the state change hasn't been externally hijacked:

https://github.com/llvm/llvm-project/blob/2fa2734690ff6debf2d678dc9f94fa14e0cbd227/lldb/source/Target/Process.cpp#L1319-L1324

  Looking at `Process::Launch()`, one of the first things done is to hijack the process events (`HijackProcessEvents()`), and only restores them when `Process::Launch()` returns.

https://github.com/llvm/llvm-project/blob/2fa2734690ff6debf2d678dc9f94fa14e0cbd227/lldb/source/Target/Process.cpp#L2502-L2504

It *looks* like because `Process::Launch()` is hijacking these events, that function also needs to manually manage the state of the RunLock (`m_public_run_lock`).  This is similar to what is done in `Process::WaitForProcessToStop()`:

https://github.com/llvm/llvm-project/blob/2fa2734690ff6debf2d678dc9f94fa14e0cbd227/lldb/source/Target/Process.cpp#L670-L673
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzNWEuTozgS_jWui8IECD8PPlTXY6Zia6Mr2t6do0OAsDUGREuiXN5fP5mSwMaP2urdyzgcGCtTmal8fpDI7LAY0Bi-5Ps7V--C7wfh4yC8_2PLK9JoUW3IYBLWSqZca1Kwpkq3ZDjURtZDZoa8MuoADERWhBHFS2k42UptBvSBFEWWkAGdvUdxEAbRgM5JJrkmlTQklUrx1BQHorkhZsvht4AFnsEfxVlG9mgBEkSVcyWkIq0VojWEZwEh99pq1k1hlZasOoD0En4zjdrBOm14PRQVWDUJkQd-rArFNwJoSvt1blI0UjambgxycaWkGsT3YMM7K0Rrm2cHDXAge5wczDFCVoHznrs-fbCyLjjs96uwzX7Nh_Er4HfwnPdbIarmg-gDmFQ6OnpwqCEuHE6Pbne3w2GBdldwPDqg96CAxhhEeqrdyy5kyoqeUPAJysWT1gUzuVSld743ZGgNccyEvHkedMMV-oOsKhs3pFfytorUMba_6BX6DF8v0yaNP8jXNMNnpYRzMPmYTdaT0bCpdpXcV45vuKkax_t9Sf4NYYYAIW8cRGEQYm64u2EU0WnAi2ngpIDZrYrfwaqKlfzEBGvolbMfuPalI9UO6uZR2MyBE24lCKDPDUTvaPo_uKp44TjiiCz_-UZWDSfPPCHRjEQToMRzuESUPC1XhIY0vPBtLgpOAtTAi8K7_qGBwqoM4R88bQxLCu4qTIKeKbD-S2O-e2vos1Zpt59O0SedD4LLWH7eBiz7m-eJRuPprKtTd85f03-h3mwJ5v01PWhIDWr8lvu2iaBvUbeB2h3Ej44bazf8COEzzeEzzbI0GoWkyIY0iKaBllCia22Ysg0Fw2_3gn2tnbiOKiEnmIYiQ7IWmwoqbfny23L1_e3CeOg1xIf_Vlc536LFr_H7M_tajq474_88EaZurqwAGodo1Bc96frZFULbHYeD-ImAtJ6kQfwwoN9AzxOqKuX7T9A_oGOla9vI4S4TR8t6u2O_O_a7oQ8WP3s8s3FITj6D-BtZZ8WpwdfMbjnWNoVb8y_Uz24bzz5a4yN6Y3dyZjzsLiwPpWEaT3GuwXZRY504WZx9nB1jJ-o1Uxv9PyZWO63OhgrOlaVhMK9KoUtmoBEk3Ow5jKO2JrUlD-ikW_nRVK8y3TmKE7XCmS8blXIiczvoPx24xJJw9sOfBzffvyd_-kkS3z9sebr7wX82Avo09CNtXTTHnRZJwE25dtLWkDywDKKqpihwSHrtT7ZnwpSAxm74B8IFAgOoJXutL0BTteJwhUVAIKstM7e2g5IUdCKuyZUsATNc4_zBc2Q2KAh2QMNu6iP6usZtz7zkZgUB5ubNqO64PQjyclPdbQEeIflmD87CyvyNGxv0o1fxZH0QJ20ELdvS92MnLWkcxGuzwGxFtdN26QTTaSMgGqqpKntui9wujAARgGh2zoygXHfs8SO2LKMabpXOL5EhrF89L9mjXkRxLRS9yBV7CJ4yqHgiDNwWgr_zixN4Y4KzAurgXtc46WnjHPFRwkcZTzIYbwnWKDSaIIphJ_5Z10q8o-dtxL4aSnCxBod0zTkdJ1GWZ5E9irGMHdl-onkym1CHazNZm3WLx4HNehX6BmTnuf4grWvQPo6mCFgmXTcbRyMyCOe99mrhng1IefSS5R2f8_q-4Y8GyYR5A8gXR9S6sPfQ5k4kTE6GCBhzLk_kmFAnu4OVOry2iTS5lmYddY5HByb8HhXOzlXgx-b-i_bZ3xbMp5WE4XDutWqmp4eaX-qwLdx6ZWXzc_lGjokKErvNNLxmICEXxjg5rwisXFGhgT72jtZ5oXP5KSa8lHh6vB67jyZQV4eaO7eO7Jx-JP2-8QUt_RCdbuhXjE-ljt0pHTkAdHQ3tJI9psb5OiHrdcYMu1xHSrcj7K9Xao2eA6jrYGef6knrPdtxaPRX9u-VgPHyCcNRwfpnwxue3WBygj5jchzXKHrL1PU9NcuiG-v02npesI0-Jwymj6dO1uI_LSql3aOsIwES2DhIOqLz0XwypfOuFE-k9KaBqyqXFi3LZ5DmTWot8GnJdnlHWkrs9oWUMKwKsbODod-ZoN02SSHSy9kIba6WlROJGGLHeY2m4cj4Ik4CEAQP7lXajlCwxY4qWcHEbeoMWU7Hqt_kwJT7k25ZteFky3QFIB8nF0AhaNvw8Alo-EC24k8G7TA7vqOw160xte6e0DfCbJskSGUJf4rivf0ZQk1aAEafk0JCnT7TnNFpPJrMwzyfwETLaTaZzrJ0ns9HOYtGPEyTjNrnQFfZzw4Bwo0bXnDjXWEHC41foziaD-FKR6cGEvIKUUF_OujVi8qrfejs4RlZdSgzF0obC0EgJTMkQLQAuzhX9EY6zHgAkh6K_G7pXtHTew9i-kaOL4RscCD4RioHEMoOf35mJGwxjap08DcNAx2HdIjXXhhewPn03hYIPmfaGmlx0n87MHjdudxXBWzh3qsPDgm3L9UIK7QkFeeZDRRg8MYmL9ywDT_Jdh_hth5c3Mp1bUsUm4Pt1x0-XAFGssBTlKJgCmXvPQJ3eXEZtT-YMM9S-bWVxHl1zIK_bRFNpuEQLvFdtoizeTxnd0aYgi_8VG4THt_GOXztHdo94YnuJeXZO6BUZrxmZosPnRuBmPjGI9xdo4rFL7tEaN1wtGs8Boh6t11QnsR0SmdhPImibJwDemZJNo75eD6KJll-VzBA53oxGH-DIVLxPbEicKCMH-_EgobwAD2iYTQdR_Es4LPZdDLLIzZO4owBihyFvGSiCNCOQKrNnVpYk5IGnqNHIb5_0kci0_iOhHOrDuSzxmylWmQlpNPhzmpeWMv_AtwMFAw">