0

I am trying with a small program from Distinction between processes and threads in Linux

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <pthread.h>

void* threadMethod(void* arg)
{
    int intArg = (int) *((int*) arg);

    int32_t pid = getpid();
    uint64_t pti = pthread_self();

    printf("[Thread %d] getpid() = %d\n", intArg, pid);
    printf("[Thread %d] pthread_self() = %lu\n", intArg, pti);
}

int main()
{
    pthread_t threads[2];

    int thread1 = 1;

    if ((pthread_create(&threads[0], NULL, threadMethod, (void*) &thread1))
         != 0)
    {
        fprintf(stderr, "pthread_create: error\n");
        exit(EXIT_FAILURE);
    }

    int thread2 = 2;

    if ((pthread_create(&threads[1], NULL, threadMethod, (void*) &thread2))
         != 0)
    {
        fprintf(stderr, "pthread_create: error\n");
        exit(EXIT_FAILURE);
    }

    int32_t pid = getpid();
    uint64_t pti = pthread_self();

    printf("[Process] getpid() = %d\n", pid);
    printf("[Process] pthread_self() = %lu\n", pti);

    if ((pthread_join(threads[0], NULL)) != 0)
    {
        fprintf(stderr, "Could not join thread 1\n");
        exit(EXIT_FAILURE);
    }

    if ((pthread_join(threads[1], NULL)) != 0)
    {
        fprintf(stderr, "Could not join thread 2\n");
        exit(EXIT_FAILURE);
    }

    return 0;
}

On 64 bit Lubuntu 18.04, I compile it by the same command from the post:

$ gcc -pthread -o thread_test thread_test.c

I also try to follow what the post says:

By using scheduler locking in gdb, I can keep the program and its threads alive so I can capture what top

but because I am not familiar with gdb, the program runs to finish without pausing (see below). I also tried to set up breakpoint by break 43, but gdb says No line 40 in the current file. What shall I do to pause the execution, so that I can use top or ps to examine the threads' pid and tgid?

$ gdb thread_test
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from thread_test...(no debugging symbols found)...done.
(gdb) set scheduler-locking
Requires an argument. Valid arguments are off, on, step, replay.
(gdb) set scheduler-locking on
Target 'exec' cannot support this command.
(gdb) run
Starting program: /tmp/test/pthreads/thread_test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff77c4700 (LWP 4711)]
[New Thread 0x7ffff6fc3700 (LWP 4712)]
[Thread 1] getpid() = 4707
[Thread 1] pthread_self() = 140737345505024
[Process] getpid() = 4707
[Process] pthread_self() = 140737353951040
[Thread 0x7ffff77c4700 (LWP 4711) exited]
[Thread 2] getpid() = 4707
[Thread 2] pthread_self() = 140737337112320
[Thread 0x7ffff6fc3700 (LWP 4712) exited]
[Inferior 1 (process 4707) exited normally]
(gdb) 
halfer
  • 19,824
  • 17
  • 99
  • 186
Tim
  • 1
  • 141
  • 372
  • 590
  • 2
    You need to compile program with `-g` flag, then you will be able to setup breakpoint. – Robert Baldyga Jan 01 '19 at 13:44
  • Thanks. The post I linked doesn't complie it with -g, but it says "By using scheduler locking in gdb, I can keep the program and its threads alive so I can capture what top" – Tim Jan 01 '19 at 13:45
  • @Eric My Lubuntu 18.04 is a general purposed OS. Is scheduler locking in gdb a feature only supported by special OSes? – Tim Jan 01 '19 at 13:58
  • Thanks. @Eric Where can I set the breakpoint, so that I can use top or ps to show all the three threads as in the original post? I only see one thread when pausing at line 43, and am not sure where I shall place the breakpoint instead. – Tim Jan 01 '19 at 15:44
  • First things first, when you set a breakpoint in `main`, then run the program, then execute `set scheduler-locking on`, do you still get an error message? – Eric Postpischil Jan 01 '19 at 15:50
  • no error message. @Eric – Tim Jan 01 '19 at 15:54
  • 1
    when compiling, always enable the warnings, then fix those warnings. Suggest using: `gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -o thread_test thread_test.c -pthread – user3629249 Jan 01 '19 at 17:09
  • the last line in the function: `threadMethod()` should be: `pthread_exit( NULL );` Otherwise the compiler will complain. – user3629249 Jan 01 '19 at 17:12
  • 1
    OT: regarding: `fprintf(stderr, "pthread_create: error\n");` This fails to tell the user why the function failed. Strongly suggest: `perror( "pthread_create failed" );` as that will output the error message and the text reason the system thinks the error occurred to `stderr` – user3629249 Jan 01 '19 at 17:20
  • 1
    Re: "The post I linked doesn't complie it with -g" You can compile without -g, but then you'll be able to place breakpoints only at functions and numeric object code addresses, not line numbers. – Mark Plotnick Jan 01 '19 at 23:15

2 Answers2

2

You have two problems:

  • you built your program without debugging info (add -g flag), and
  • you are trying to set scheduler-locking on before the program started (that doesn't work).

This should work:

 gcc -g -pthread -o thread_test thread_test.c
 gdb -q ./thread_test
 (gdb) start
 (gdb) set scheduler-locking on

However, you must be extra careful with this setting -- simply continuing from this point will get your program to block in pthread_join, as only the main thread will keep running.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
1

the following is an example of using gdb with the posted code to pause everything:

note: this was compiled to find/fix compile problems via:

gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c untitled.c

this was finally compiled/linked via:

gcc -ggdb -Wall -o untitled untitled.c   -lpthread 

then using the debugger: gdb, thereby showing my inputs and the gdb outputs:

$ gdb untitled
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from untitled...done.
(gdb) br main
Breakpoint 1 at 0x9a5: file untitled.c, line 20.
(gdb) br threadMethod
Breakpoint 2 at 0x946: file untitled.c, line 9.
(gdb) r
Starting program: /home/richard/Documents/forum/untitled 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at untitled.c:20
20  {
(gdb) c
Continuing.
[New Thread 0x7ffff77c4700 (LWP 8645)]
[New Thread 0x7ffff6fc3700 (LWP 8646)]
[Switching to Thread 0x7ffff77c4700 (LWP 8645)]

Thread 2 "untitled" hit Breakpoint 2, threadMethod (arg=0x7fffffffdf4c)
    at untitled.c:9
9       int intArg = (int) *((int*) arg);
(gdb) 

then you can (in another terminal window) use ps etc to display info. However, the thread function will output (to stdout the information you might be interested in.

or you can (in gdb enter commands like:

(gdb) c
[Process] getpid() = 8641
[Process] pthread_self() = 140737353992000
[Switching to Thread 0x7ffff6fc3700 (LWP 8646)]

Thread 3 "untitled" hit Breakpoint 2, threadMethod (arg=0x7fffffffdf50)
at untitled.c:9
9       int intArg = (int) *((int*) arg);
(gdb) c
....
[Thread 1] getpid() = 8641
[Thread 1] pthread_self() = 140737345505024
....
[Thread 2] getpid() = 8641
[Thread 2] pthread_self() = 140737337112320
user3629249
  • 16,402
  • 1
  • 16
  • 17