diff options
author | rsesek@chromium.org <rsesek@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2014-05-05 20:36:06 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2014-05-05 20:36:06 +0000 |
commit | 44ba0b2050f22376d623663652395de079a4b713 (patch) | |
tree | a250cd2d020782046d4f3b0052e55941dc724f9e /src/client | |
parent | Fixing a build break on Linux. (diff) | |
download | breakpad-44ba0b2050f22376d623663652395de079a4b713.tar.xz |
Make the Linux CrashGenerationClient an interface.
Also allow it to be set on the ExceptionHandler. This will allow Chromium's
implementation to be properly treated as an out-of-process handler.
BUG=https://code.google.com/p/chromium/issues/detail?id=349600
R=mark@chromium.org
Review URL: https://breakpad.appspot.com/2664002
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1324 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client')
3 files changed, 81 insertions, 70 deletions
diff --git a/src/client/linux/crash_generation/crash_generation_client.cc b/src/client/linux/crash_generation/crash_generation_client.cc index 6ede7791..aed13e14 100644 --- a/src/client/linux/crash_generation/crash_generation_client.cc +++ b/src/client/linux/crash_generation/crash_generation_client.cc @@ -27,66 +27,77 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "client/linux/crash_generation/crash_generation_client.h" + #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <algorithm> -#include "client/linux/crash_generation/crash_generation_client.h" #include "common/linux/eintr_wrapper.h" #include "common/linux/ignore_ret.h" -#include "common/linux/linux_libc_support.h" #include "third_party/lss/linux_syscall_support.h" namespace google_breakpad { -bool -CrashGenerationClient::RequestDump(const void* blob, size_t blob_size) -{ - int fds[2]; - sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds); - static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int)); - - struct kernel_msghdr msg; - my_memset(&msg, 0, sizeof(struct kernel_msghdr)); - struct kernel_iovec iov[1]; - iov[0].iov_base = const_cast<void*>(blob); - iov[0].iov_len = blob_size; - - msg.msg_iov = iov; - msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]); - char cmsg[kControlMsgSize]; - my_memset(cmsg, 0, kControlMsgSize); - msg.msg_control = cmsg; - msg.msg_controllen = sizeof(cmsg); - - struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg); - hdr->cmsg_level = SOL_SOCKET; - hdr->cmsg_type = SCM_RIGHTS; - hdr->cmsg_len = CMSG_LEN(sizeof(int)); - int* p = reinterpret_cast<int*>(CMSG_DATA(hdr)); - *p = fds[1]; - - ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0)); - sys_close(fds[1]); - if (ret <= 0) - return false; - - // wait for an ACK from the server - char b; - IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1))); - - return true; -} +namespace { + +class CrashGenerationClientImpl : public CrashGenerationClient { + public: + explicit CrashGenerationClientImpl(int server_fd) : server_fd_(server_fd) {} + virtual ~CrashGenerationClientImpl() {} + + virtual bool RequestDump(const void* blob, size_t blob_size) { + int fds[2]; + if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) + return false; + static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int)); + + struct kernel_iovec iov; + iov.iov_base = const_cast<void*>(blob); + iov.iov_len = blob_size; + + struct kernel_msghdr msg = { 0 }; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + char cmsg[kControlMsgSize] = ""; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof(cmsg); -//static -CrashGenerationClient* -CrashGenerationClient::TryCreate(int server_fd) -{ - if (0 > server_fd) + struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg); + hdr->cmsg_level = SOL_SOCKET; + hdr->cmsg_type = SCM_RIGHTS; + hdr->cmsg_len = CMSG_LEN(sizeof(int)); + int* p = reinterpret_cast<int*>(CMSG_DATA(hdr)); + *p = fds[1]; + + ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0)); + sys_close(fds[1]); + if (ret < 0) + return false; + + // Wait for an ACK from the server. + char b; + IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1))); + sys_close(fds[0]); + + return true; + } + + private: + int server_fd_; + + DISALLOW_COPY_AND_ASSIGN(CrashGenerationClientImpl); +}; + +} // namespace + +// static +CrashGenerationClient* CrashGenerationClient::TryCreate(int server_fd) { + if (server_fd < 0) return NULL; - return new CrashGenerationClient(server_fd); + return new CrashGenerationClientImpl(server_fd); } -} +} // namespace google_breakpad diff --git a/src/client/linux/crash_generation/crash_generation_client.h b/src/client/linux/crash_generation/crash_generation_client.h index 7139dff4..4e68424a 100644 --- a/src/client/linux/crash_generation/crash_generation_client.h +++ b/src/client/linux/crash_generation/crash_generation_client.h @@ -30,40 +30,36 @@ #ifndef CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ #define CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ +#include "common/basictypes.h" + #include <stddef.h> namespace google_breakpad { +// CrashGenerationClient is an interface for implementing out-of-process crash +// dumping. The default implementation, accessed via the TryCreate() factory, +// works in conjunction with the CrashGenerationServer to generate a minidump +// via a remote process. class CrashGenerationClient { -public: - ~CrashGenerationClient() - { - } + public: + CrashGenerationClient() {} + virtual ~CrashGenerationClient() {} - // Request the crash server to generate a dump. |blob| is a hack, - // see exception_handler.h and minidump_writer.h - // - // Return true if the dump was successful; false otherwise. - bool RequestDump(const void* blob, size_t blob_size); + // Request the crash server to generate a dump. |blob| is an opaque + // CrashContext pointer from exception_handler.h. + // Returns true if the dump was successful; false otherwise. + virtual bool RequestDump(const void* blob, size_t blob_size) = 0; - // Return a new CrashGenerationClient if |server_fd| is valid and + // Returns a new CrashGenerationClient if |server_fd| is valid and // connects to a CrashGenerationServer. Otherwise, return NULL. // The returned CrashGenerationClient* is owned by the caller of // this function. static CrashGenerationClient* TryCreate(int server_fd); -private: - CrashGenerationClient(int server_fd) : server_fd_(server_fd) - { - } - - int server_fd_; - - // prevent copy construction and assignment - CrashGenerationClient(const CrashGenerationClient&); - CrashGenerationClient& operator=(const CrashGenerationClient&); + private: + DISALLOW_COPY_AND_ASSIGN(CrashGenerationClient); }; -} // namespace google_breakpad +} // namespace google_breakpad -#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ +#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_ diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h index e906e7a7..1de38616 100644 --- a/src/client/linux/handler/exception_handler.h +++ b/src/client/linux/handler/exception_handler.h @@ -146,6 +146,10 @@ class ExceptionHandler { crash_handler_ = callback; } + void set_crash_generation_client(CrashGenerationClient* client) { + crash_generation_client_.reset(client); + } + // Writes a minidump immediately. This can be used to capture the execution // state independently of a crash. // Returns true on success. @@ -200,7 +204,7 @@ class ExceptionHandler { // Returns whether out-of-process dump generation is used or not. bool IsOutOfProcess() const { - return crash_generation_client_.get() != NULL; + return crash_generation_client_.get() != NULL; } // Add information about a memory mapping. This can be used if |