blob: 0a958f4025f8f2282e2b2fd8f06105f2c77e1d96 [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.
#ifndef KUDU_UTIL_PSTACK_WATCHER_H
#define KUDU_UTIL_PSTACK_WATCHER_H
#include <sys/types.h>
#include <string>
#include <vector>
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/condition_variable.h"
#include "kudu/util/monotime.h"
#include "kudu/util/mutex.h"
#include "kudu/util/status.h"
namespace kudu {
class Thread;
// PstackWatcher is an object which will pstack the current process and print
// the results to stdout. It does this after a certain timeout has occured.
class PstackWatcher {
public:
enum Flags {
NO_FLAGS = 0,
// Run 'thread apply all bt full', which is very verbose output
DUMP_FULL = 1
};
// Static method to collect and write stack dump output to stdout of the current
// process.
static Status DumpStacks(int flags = NO_FLAGS);
// Like the above but for any process, not just the current one.
static Status DumpPidStacks(pid_t pid, int flags = NO_FLAGS);
// Instantiate a watcher that writes a pstack to stdout after the given
// timeout expires.
explicit PstackWatcher(MonoDelta timeout);
~PstackWatcher();
// Shut down the watcher and do not log a pstack.
// This method is not thread-safe.
void Shutdown();
// Test whether the watcher is still running or has shut down.
// Thread-safe.
bool IsRunning() const;
// Wait until the timeout expires and the watcher logs a pstack.
// Thread-safe.
void Wait() const;
private:
// Test for the existence of the given program in the system path.
static Status HasProgram(const char* progname);
// Check whether the system path has 'gdb' and whether it is modern enough
// for safe stack dump usage.
static Status HasGoodGdb();
// Get a stack dump using GDB directly.
static Status RunGdbStackDump(pid_t pid, int flags);
// Get a stack dump using the pstack or gstack program.
static Status RunPstack(const std::string& progname, pid_t pid);
#if defined(__APPLE__)
// Check whether the system path has 'sample'
static Status HasGoodSample();
// Get a stack dump using sample directly.
static Status RunSampleStackDump(pid_t pid);
#endif
// Invoke and wait for the stack dump program.
static Status RunStackDump(const std::vector<std::string>& argv);
// Run the thread that waits for the specified duration before logging a
// pstack.
void Run();
const MonoDelta timeout_;
bool running_;
scoped_refptr<Thread> thread_;
mutable Mutex lock_;
mutable ConditionVariable cond_;
};
} // namespace kudu
#endif