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 crash with using C++ thread #66

Merged
merged 1 commit into from
May 1, 2020

Conversation

d3m3vilurr
Copy link
Contributor

disable GTHREAD_USE_WEAK flag like lynx, darwin, cygwin and
others.

test sample;

std::once_flag flag;

void thread() {
    try {
        std::call_once(flag, [](){
        });
    } catch (...) {
    }
}

int main(int argc, char *argv[]) {
    psvDebugScreenInit();
    printf("testing try-catch\n");

    if (!pthread_init()) {
        printf("thread init error\n");
    }

    printf("run thread\n");

    std::thread t{thread};

    printf("try join thread\n");

    try {
        t.join();
    } catch (...) {
        printf("try join thread err\n");
    }

    printf("end thread\n");
    sceKernelDelayThread(10000*1000);
    return 0;
}

disassemble of before patch;

0000d88c <_ZNSt6thread4joinEv>:
    d88c:       b510            push    {r4, lr}
    d88e:       4604            mov     r4, r0
    d890:       6800            ldr     r0, [r0, #0]
    d892:       b128            cbz     r0, d8a0 <_ZNSt6thread4joinEv+0x14>
    d894:       2100            movs    r1, #0
    d896:       f3af 8000       nop.w
    d89a:       b910            cbnz    r0, d8a2 <_ZNSt6thread4joinEv+0x16>
    d89c:       6020            str     r0, [r4, #0]
    d89e:       bd10            pop     {r4, pc}
    d8a0:       2016            movs    r0, #22
    d8a2:       f7fa fbcd       bl      8040 <_ZSt20__throw_system_errori>
    d8a6:       bf00            nop

when I get the disassemble code of the output, it doesn't have
pthread_join.
then process would call throw_system_error.

more bad things, process will occur crash whether wrapping try-catch block
or not.
crash with try-catch case would happen at the end of the application,
thread try to call the _kill_r, then occurs crash.

disassemble of after patch;

0000e69c <_ZNSt6thread4joinEv>:
    e69c:       b510            push    {r4, lr}
    e69e:       4604            mov     r4, r0
    e6a0:       6800            ldr     r0, [r0, #0]
    e6a2:       b128            cbz     r0, e6b0 <_ZNSt6thread4joinEv+0x14>
    e6a4:       2100            movs    r1, #0
    e6a6:       f7fe fd19       bl      d0dc <pthread_join>
    e6aa:       b910            cbnz    r0, e6b2 <_ZNSt6thread4joinEv+0x16>
    e6ac:       6020            str     r0, [r4, #0]
    e6ae:       bd10            pop     {r4, pc}
    e6b0:       2016            movs    r0, #22
    e6b2:       f7f9 fcc5       bl      8040 <_ZSt20__throw_system_errori>
    e6b6:       bf00            nop

now, we can get the pthread_join, waiting end of the thread is normal.

disable `GTHREAD_USE_WEAK` flag like lynx, darwin, cygwin and
others.

test sample;
```
std::once_flag flag;

void thread() {
    try {
        std::call_once(flag, [](){
        });
    } catch (...) {
    }
}

int main(int argc, char *argv[]) {
    psvDebugScreenInit();
    printf("testing try-catch\n");

    if (!pthread_init()) {
        printf("thread init error\n");
    }

    printf("run thread\n");

    std::thread t{thread};

    printf("try join thread\n");

    try {
        t.join();
    } catch (...) {
        printf("try join thread err\n");
    }

    printf("end thread\n");
    sceKernelDelayThread(10000*1000);
    return 0;
}

```

disassemble of before patch;
```
0000d88c <_ZNSt6thread4joinEv>:
    d88c:       b510            push    {r4, lr}
    d88e:       4604            mov     r4, r0
    d890:       6800            ldr     r0, [r0, #0]
    d892:       b128            cbz     r0, d8a0 <_ZNSt6thread4joinEv+0x14>
    d894:       2100            movs    r1, #0
    d896:       f3af 8000       nop.w
    d89a:       b910            cbnz    r0, d8a2 <_ZNSt6thread4joinEv+0x16>
    d89c:       6020            str     r0, [r4, #0]
    d89e:       bd10            pop     {r4, pc}
    d8a0:       2016            movs    r0, vitasdk#22
    d8a2:       f7fa fbcd       bl      8040 <_ZSt20__throw_system_errori>
    d8a6:       bf00            nop
```

when I get the disassemble code of the output, it doesn't have
`pthread_join`.
then process would call `throw_system_error`.

more bad things, process will occur crash whether wrapping try-catch block
or not.
crash with try-catch case would happen at the end of the application,
`thread` try to call the `_kill_r`, then occurs crash.

disassemble of after patch;
```
0000e69c <_ZNSt6thread4joinEv>:
    e69c:       b510            push    {r4, lr}
    e69e:       4604            mov     r4, r0
    e6a0:       6800            ldr     r0, [r0, #0]
    e6a2:       b128            cbz     r0, e6b0 <_ZNSt6thread4joinEv+0x14>
    e6a4:       2100            movs    r1, #0
    e6a6:       f7fe fd19       bl      d0dc <pthread_join>
    e6aa:       b910            cbnz    r0, e6b2 <_ZNSt6thread4joinEv+0x16>
    e6ac:       6020            str     r0, [r4, #0]
    e6ae:       bd10            pop     {r4, pc}
    e6b0:       2016            movs    r0, vitasdk#22
    e6b2:       f7f9 fcc5       bl      8040 <_ZSt20__throw_system_errori>
    e6b6:       bf00            nop
```

now, we can get the `pthread_join`, waiting end of the thread is normal.
@d3m3vilurr
Copy link
Contributor Author

I didn't test with complex codeset. just check the built result. :)

@blastrock
Copy link

Hi,

I am not sure this really is the solution to your problem. Is that the disassembly of the .o files? It is normal for .o file to be missing calls, they are filled in at link time. If you want to see calls to other files, disassemble the final binary, not the .o.

Also, if you think this crashes because of the throw_system_error, it occurs only when pthread is not linked. If you use pthread, you must add -lpthread to the compilation line.

This is just some advice based on my knowledge, I didn't test the program. If GTHREAD_USE_WEAK really is your problem, I think it's ok to disable it.

@d3m3vilurr
Copy link
Contributor Author

it's final binary & I'm added -lpthread.

target_link_libraries(${PROJECT_NAME}
  SceLibKernel_stub
  SceDisplay_stub
  pthread
  stdc++
)

linking setup is here.

and I've tested with both of latest toolchain & my own built version. :)

another solution is adding the internal method on the pthread-embedded.
(when I define the weak function named by__gthrw_pthread_join, problem was also resolved)

@blastrock
Copy link

I guess this is fine then :)

@d3m3vilurr
Copy link
Contributor Author

pr was reviewed by two people. I'll merge it now. :>

@d3m3vilurr d3m3vilurr merged commit ba44b03 into vitasdk:master May 1, 2020
@d3m3vilurr d3m3vilurr deleted the fix-cpp-thread branch May 1, 2020 18:19
frangarcj added a commit that referenced this pull request Jun 6, 2020
frangarcj added a commit that referenced this pull request Jun 6, 2020
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.

2 participants