blob: 48e2662cff01d7d66b376eed2da15b243e5d9159 [file] [log] [blame]
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# A collection of useful Python GDB modules and commands for
# debugging Impala core dumps.
#
import gdb
from collections import defaultdict
def get_fragment_instances():
# Walk the threadlist to find fragment instance ids. Assumes IMPALA-6416, so
# this will not work with releases older than Impala 2.12. It may be possible
# to search for FragmentInstanceState::Exec() in the older releases to get
# to the FInstIDs. Returns a dictionary of FInstID->[gdb thread ID].
# Note that multiple threads might be doing tasks for the same FInstID.
fragment_instances = defaultdict(list)
for thread in gdb.selected_inferior().threads():
thread.switch()
f = gdb.newest_frame()
while f:
# Skip unresolved frame
if gdb.Frame.name(f) is None:
f = gdb.Frame.older(f)
continue
if 'impala::Thread::SuperviseThread' in gdb.Frame.name(f):
gdb.Frame.select(f)
block = gdb.Frame.block(f)
gdb.lookup_symbol('thread_debug_info', block)
tdi = f.read_var('thread_debug_info')
# No valid thread_debug_info
if not tdi:
break
hi = long(tdi['instance_id_']['hi'])
lo = long(tdi['instance_id_']['lo'])
fi = "%lx:%lx" % (hi, lo)
if fi != "0:0":
fragment_instances[fi.strip('"')].append(thread.num)
break
f = gdb.Frame.older(f)
return fragment_instances
class FindFragmentInstances(gdb.Command):
"""Find all query fragment instance to thread Id mappings in this impalad."""
def __init__(self):
super(FindFragmentInstances, self).__init__(
"find-fragment-instances",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
False)
def invoke(self, arg, from_tty):
fragment_instances = get_fragment_instances()
print('Fragment Instance Id\tThread IDs\n')
for fid in sorted(fragment_instances):
print("{}\t{}".format(fid, fragment_instances[fid]))
class FindQueryIds(gdb.Command):
"""Find IDs of all queries this impalad is currently executing."""
def __init__(self):
super(FindQueryIds, self).__init__(
"find-query-ids",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE,
False)
def invoke(self, arg, from_tty):
fragment_instances = get_fragment_instances()
query_ids = set()
for fi in fragment_instances:
qid_hi, qid_low = fi.split(':')
qid_low = format(int(qid_low, 16) & 0xFFFFFFFFFFFF0000, 'x')
query_ids.add("{}:{}".format(qid_hi, qid_low))
print('\n'.join(query_ids))
# Instantiate the command classes so they can be invoked from within GDB
FindFragmentInstances()
FindQueryIds()