Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

core dump filename gets thread name instead of executable name with core_pattern %e.%p.core

I recently started setting some thread names within my application by using pthread_setname_np(). After doing this, if a crash occurs within one of the named threads, the core dump filename is getting the thread name instead of executable name with core_pattern %e.%p.core

According to the core man page, the %e flag in the core_pattern is supposed to get expanded to the executable name. It doesn't say anything about the thread name.

I want the executable name and not the thread name, because I have other automated scripts (not maintained by me) that depend on the core filenames beginning with the application name.

Is this a bug in pthread_setname_np() or core_pattern?

I am running on Linux CentOS 6.7.

like image 872
jfritz42 Avatar asked Jan 14 '16 22:01

jfritz42


People also ask

What is kernel core_pattern?

core_pattern is used to specify a core dumpfile pattern name. max length 128 characters; default value is “core” core_pattern is used as a pattern template for the output filename; certain string patterns (beginning with '%') are substituted with their actual values.

How do I change my kernel core pattern?

You can update the core_pattern file with the necessary % specifiers. For example, run the following command: echo "/var/imabridge/core. %E. %p " > /proc/sys/kernel/core_pattern .

How do I analyze a core dump file?

With a core file, we can use the debugger (GDB) to inspect the state of the process at the moment it was terminated and to identify the line of code that caused the problem. That's a situation where a core dump file could be produced, but it's not by default.

What is core PID file?

By default, the core file is called core or core.pid, where pid is the ID of the process that dumped core, and is created in the current working directory. See below for details on naming.)


2 Answers

So I wound up working around the issue by piping the core dump to a Python script which then renames the core filename based on a hard-coded mapping of thread name regex patterns to executable name.

Here's how to pipe the core to a script:

/sbin/sysctl -q -w "kernel.core_pattern=|/opt/mydirectory/bin/core_helper.py --corefile /opt/mydirectory/coredumps/%e.%p.core"
/sbin/sysctl -q -w "kernel.core_pipe_limit=8"

Here's a snippet of a class in core_helper.py. As a bonus, if you give the core filename a .gz extension, it will compress the coredump with gzip.

class CoredumpHelperConfig:
    def __init__(self, corefile):
        self.corefile = corefile

    # Work-around: Linux is putting the thread name into the 
    # core filename instead of the executable. Revert the thread name to 
    # executable name by using this mapping.
    # The order is important -- the first match will be used. 
    threadNameToExecutableMapping = [# pattern       , replace
                                      (r'fooThread.*', r'foo'),
                                      (r'barThread.*', r'foo'),
                                    ]

    def processCore(self):
        (dirname, basename) = os.path.split(self.corefile)
        # E.g. fooThread0.21495.core (no compression) or fooThread0.21495.core.gz (compression requested)
        match = re.match(r'^(\w+)\.(\d+)\.(core(\.gz)?)$', basename)
        assert match
        (threadName, pid, ext, compression) = match.groups()
        # Work-around for thread name problem
        execName = threadName
        for (pattern, replace) in CoredumpHelperConfig.threadNameToExecutableMapping:
            match = re.match(pattern, threadName)
            if match:
                execName = re.sub(pattern, replace, threadName)
                break
        self.corefile = os.path.join(dirname, '.'.join([execName, pid, ext]))
        # Pipe the contents of the core into corefile, optionally compressing it
        core = open(self.corefile, 'w')
        coreProcessApp = "tee"
        if(compression):
            coreProcessApp = "gzip"
        p = subprocess.Popen(coreProcessApp, shell=True, stdin=sys.stdin, stdout=core, stderr=core)
        core.close()
        return True

I'll leave it as an exercise to the reader on how to write the rest of the file.

like image 141
jfritz42 Avatar answered Sep 30 '22 10:09

jfritz42


The executable name that generated the core can be retrieved by using gdb. The following prints it:

gdb -batch -ex "core corefile" | grep "Core was generated" | cut -d\` -f2 | cut -d"'" -f1 | awk '{print $1}'

Or better yet use the pid %p and /proc to get it. Example:

$ sleep 900 &
[1] 2615
$ readlink /proc/$(pidof sleep)/exe
/bin/sleep
$ basename $(readlink /proc/$(pidof sleep)/exe)
sleep
like image 41
Dave C Avatar answered Sep 30 '22 12:09

Dave C