diff options
Diffstat (limited to 'src/client/linux/crash_generation/crash_generation_client.cc')
-rw-r--r-- | src/client/linux/crash_generation/crash_generation_client.cc | 105 |
1 files changed, 58 insertions, 47 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 |