https://mysqlentomologist.blogspot.jp/2017/07/

 
 
 
 
 

Saturday, July 29, 2017

How to Find Processlist Thread id in gdb

 
I was involved in a discussion on some complex MySQL-related problem where we had to study backtraces of all threads in gdb (produced by the thread apply all bt command if you ever forgets this) in a hope to find out why MySQL hangs. In the process the question appeared on how to find the thread id for each thread to match it against previous collected outputs of SHOW PROCESSLIST. and SHOW ENGINE INNODB STATUS.

I assumed I know the answer, as I had to find this out recently enough for this blog post (and before that for the real customer case). The idea is simple. Find a frame where function has a parameter of THD * type (usually named thd), like this:

#10 0x0000000000cb47fe in do_command (thd=0x7f32512b7000)
    at /usr/src/debug/percona-server-5.7.18-15/percona-server-5.7.18-15/sql/sql_parse.cc:960

and check thread_id item of this structure.

In that my blog post it looked as simple as just referring to thd of do_command's frame without even checking much:

(gdb) thread 2
[Switching to thread 2 (Thread 0x7f7f5ce02b00 (LWP 9232))]
#0  pthread_cond_timedwait@@GLIBC_2.3.2 ()
    at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:238
238     ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: No such file or directory.
(gdb) p do_command::thd->thread_id
$9 = 14

I prefer to double check my suggestions before making them, so I immediately tried this with my CentOS 6.9 VM running recent Percona Server 5.7.x by default since that times when I worked at Percona:

[root@centos ~]# gdb -p `pidof mysqld`
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-92.el6)
...
Loaded symbols for /usr/lib64/mysql/plugin/tokudb_backup.so
0x00007f550ad35383 in poll () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.209.el6_9.2.x86_64 jemalloc-3.6.0-1.el6.x86_64 keyutils-libs-1.4-5.el6.x86_64 krb5-libs-1.10.3-65.el6.x86_64 libaio-0.3.107-10.el6.x86_64 libcom_err-1.41.12-23.el6.x86_64 libgcc-4.4.7-18.el6.x86_64 libselinux-2.0.94-7.el6.x86_64 libstdc++-4.4.7-18.el6.x86_64 nss-softokn-freebl-3.14.3-23.3.el6_8.x86_64 numactl-2.0.9-2.el6.x86_64 openssl-1.0.1e-57.el6.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) thread 1
[Switching to thread 1 (Thread 0x7f550d2b2820 (LWP 1978))]#0  0x00007f550ad35383 in poll () from /lib64/libc.so.6
(gdb) p do_command::thd->thread_id
No frame is currently executing in block do_command(THD*).
(gdb) thread 2
[Switching to thread 2 (Thread 0x7f54d837b700 (LWP 2183))]#0  0x00007f550ad35383 in poll () from /lib64/libc.so.6
(gdb) p do_command::thd->thread_id
Cannot take address of method thread_id.
(gdb) call do_command::thd->thread_id()
Cannot evaluate function -- may be inlined

As you can see I started to check threads one by one and apply that good old trick. Thread 1 had no frame executing do_command(), but I did not gave up and proceeded to the next thread, as I knew I had at least one active connection (I checked the output of SHOW PROCESSLIST). There I had a surprise, no way to get thread_id of thd. I used tab completion, so I know that thread_id (variable or method) exists, but attempt to call it also failed as you can see.

This is a problem with using gdb-based "tricks" over the code that evolves/changes in time. Last time I used p do_command::thd->thread_id it was for MariaDB 10.1.x probably, and the item was there. But in MySQL 5.7 (and all forks based on it) there were many code changes, so we should be ready to changes in unexpected places.

I had not added more comments on finding thread id to that discussion, made a note to myself and then, later, decided to check the source code of MySQL 5.7 (I did not have Percona 5.7 one at hand, but they hardly differs in such basic details) to find out what had changed in the THD structure so that thread_id is not longer just a variable. I expect to see the structure defined in sql/sql_class.h from the past, but grep will help to find this out even if it's no longer the case:

[root@centos mysql-server]# grep -n "class THD" sql/*.h
sql/debug_sync.h:27:class THD;
sql/derror.h:24:class THD;
sql/event_data_objects.h:40:class THD;
...
sql/sql_class.h:1412:class THD :public MDL_context_owner,
sql/sql_class.h:4175:    raise_error() or raise_warning() methods provided by class THD.
sql/sql_cmd.h:25:class THD;
...

I found the following there:

class THD :public MDL_context_owner,
           public Query_arena,
           public Open_tables_state
{
...
private:
  my_thread_id  m_thread_id;public:
...
  /**
    Assign a value to m_thread_id by calling
    Global_THD_manager::get_new_thread_id().
  */
  void set_new_thread_id();
  my_thread_id thread_id() const { return m_thread_id; }...

So, in MySQL 5.7 thread_id() is, indeed, a method that was inlined, and essentially it returns private m_thread_id item. Benefits of C++... I had highlighted Global_THD_manager singleton also as during my next gdb sessions I had found out that simple global list of threads is also gone and in 5.7 everything is done via that Global_THD_manager. This is a topic for some other post, though.

At least now I know what to do in gdb:

...
(gdb) thread 7[Switching to thread 7 (Thread 0x7f54d8236700 (LWP 2275))]#0  0x00007f550ad35383 in poll () from /lib64/libc.so.6
(gdb) p do_command::thd->m_thread_id
$1 = 86
(gdb) p do_command::thd->m_main_security_ctx
$3 = {m_user = {m_ptr = 0x7f5500fdaf90 "myuser", m_length = 6,
    m_charset = 0x1ded640, m_alloced_length = 8, m_is_alloced = true},
  m_host = {m_ptr = 0x7f54d98ab090 "localhost", m_length = 9,
    m_charset = 0x1ded640, m_alloced_length = 16, m_is_alloced = true},
  m_ip = {m_ptr = 0x7f54f0eb0210 "127.0.0.1", m_length = 9,
    m_charset = 0x1ded640, m_alloced_length = 16, m_is_alloced = true},
  m_host_or_ip = {m_ptr = 0x7f54d98ab090 "localhost", m_length = 9,
    m_charset = 0x1ded640, m_alloced_length = 0, m_is_alloced = false},
  m_external_user = {m_ptr = 0x15167ab "", m_length = 0,
    m_charset = 0x1ded640, m_alloced_length = 0, m_is_alloced = false},
  m_priv_user = "myuser", '\000' <repeats 89 times>, m_priv_user_length = 6,
  m_proxy_user = '\000' <repeats 161 times>, m_proxy_user_length = 0,
  m_priv_host = "localhost", '\000' <repeats 51 times>,
  m_priv_host_length = 9, m_master_access = 1589248, m_db_access = 0,
  m_password_expired = false}
...

So, I know that specific thread  7 was for a session with Id 86 in the output of SHOW PROCESSLIST, and (from m_main_security_ctx, also a new name for old things in 5.7) I know it was a session of myuser connecting locally.

To summarize, there were notable changes in MySQL 5.7 in THD structure and threads management-related code in general, so make sure to re-check your "old gdb tricks" when you start working with 5.7. Reading the code helps.

Unfortunately (for gdb beginners like me) a lot of C++ approaches were introduced, including singletons, iterators based on templates instead of simple double linked lists etc, so one has to work hard to adapt to these. I hope to discuss some of my further findings and new "C++ specific" and "MySQL 5.7 specific" approaches studying MySQL in gdb in my upcoming posts.

How to Find Processlist Thread id in gdb !!!!!GDB 使用的更多相关文章

  1. cuda中thread id

    //////////////////////////////////////////////////////////////////////////// // // Copyright 1993-20 ...

  2. thread::id

    线程标识符id可以通过thread::get_id()获得,若thread obejct没有和任何线程关联则返回一个NULL的std::thread::id表示没有任何线程.当前线程若想获得自己的id ...

  3. [skill][gdb] gdb 多线程调试

    中文快速入门: http://coolshell.cn/articles/3643.html (关于多线程的部署说的并不太对) 进阶: 多进程相关概念: inferiors 是什么? http://m ...

  4. show processlist 输出ID 和 information_schema.PROCESSLIST 的id,information_schema.innodb_trx的TRX_MYSQL_T

    Session 1: mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> update Client ...

  5. 根据 thread id 停止一个线程

    出自 https://github.com/Bogdanp/dramatiq/blob/master/dramatiq/middleware/threading.py#L62 thread_id = ...

  6. GDB gdb 调试

    除了用grmon看汇编调试外,还可以用gdb. 编译的时候加-g gdb app即可进入gdb调试 设置断点:b main.c:10 然后运行程序:run 断点处可以查看变量:display a 其它 ...

  7. std::thread中获取当前线程的系统id

    std::thread不提供获取当前线程的系统id的方法,仅可以获取当前的线程id,但是我们可以通过建立索引表的方式来实现 std::mutex m; std::map<std::thread: ...

  8. 锁大全与 GDB调试

    1.innodb_lock_monitor:打开锁信息的方式 mysql> create table innodb_lock_monitor(id int) engine=InnoDB; Que ...

  9. Mysql thread 与 OS thread

    测试环境信息如下: OS:Ubuntu 16.04 LTS Mysql:Mysql 5.7.18,使用docker images运行的实例 Mysql如何处理client请求 在Mysql中,连接管理 ...

随机推荐

  1. 国内能用的NTP服务器及和标准源的偏差值

    中国境内可以使用的NTP服务器的IP地址,和泰福特服务器的时间偏差值,泰福特时钟服务器实时连接天线,测试前已经连接天线超过72小时 time-a.nist.gov 129.6.15.28 NIST, ...

  2. java 使用内部类的理由

    每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响 内部类有效的实现了多重继承,也就是说,内部类允许继承多个非接口类型(类或抽象类) 如 ...

  3. php-fpm进程管理方式(static和dynamic)

    目前最新5.3.x的php-fpm,有两种管理进程的方式,分别是static和dynamic. 如果设置成static,进程数自始至终都是pm.max_children指定的数量,pm.start_s ...

  4. 关于ARM指令那些你必须知道的东西

    1.32位ARM指令每一位都有其作用,具体如下: 低12为第二操作数, 12~15位为目的寄存器, 16~19位为第一操作数, 20~27就是操作码, 28~31就是条件域. 2.多寄存器load和s ...

  5. HTML5元素2

    用于分组的元素 元素 说明 类型 HTML5与其他的变化 blockquote 表示引自他处的大段内容 流 无变化 dd 用在dl元素之中,表示定义 无 无变化 div 一个没有任何既定语义的通用元素 ...

  6. 一行代码实现Okhttp,Retrofit,Glide下载上传进度监听

    https://mp.weixin.qq.com/s/bopDUFMB7EiK-MhLc3KDXQ essyan 鸿洋 2017-06-29 本文作者 本文由jessyan投稿. jessyan的博客 ...

  7. Drawable子类之——StateListDrawable (选择器)

    Drawable子类之——StateListDrawable (选择器) https://www.jianshu.com/p/7257ce82c762 本文出自 “阿敏其人” 简书博客,转载或引用请注 ...

  8. IEEEXtreme 极限编程大赛题解

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 IEEEXtreme全球极限编程挑战赛,是由IEEE主办,IEEE学生分会组织承办.IEEE会员参与指导和监督的.IEEE学生会员以团队 ...

  9. swftools中的pdf2swf转换Error overflow ID 65535 解决办法

    近几日因为项目需要在线转换pdf到swf实现电子期刊阅读,用到了这个工具,版本是:swftools-0.9.2.tar.gz 当然也遇到了很头疼的问题,那就是在转换pdf中色彩图形比较复杂的页时会抛出 ...

  10. 【LOJ】#2291. 「THUSC 2016」补退选

    题解 在trie树上开vector记录一下这个前缀出现次数第一次达到某个值的下标,以及记录一下现在这个前缀有多少个 为什么thusc有那么水的题--是为了防我这种cai ji爆零么= = 代码 #in ...