From 5daa41904a02ab68b872758bc17a5d066244e5c2 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Mon, 30 Jan 2023 11:33:04 +0100 Subject: [PATCH] Add ScopedPipe. This provides a similar wrapper to ScopedTmpFile for linux pipes. Change-Id: I53b377085322f61d87525d215ecd703f13ae9ae7 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3971918 Reviewed-by: Lei Zhang --- Makefile.am | 12 +++ Makefile.in | 77 ++++++++++++++ src/common/linux/scoped_pipe.cc | 128 +++++++++++++++++++++++ src/common/linux/scoped_pipe.h | 115 ++++++++++++++++++++ src/common/linux/scoped_pipe_unittest.cc | 71 +++++++++++++ 5 files changed, 403 insertions(+) create mode 100644 src/common/linux/scoped_pipe.cc create mode 100644 src/common/linux/scoped_pipe.h create mode 100644 src/common/linux/scoped_pipe_unittest.cc diff --git a/Makefile.am b/Makefile.am index dea7b53d..da13cce1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -223,6 +223,7 @@ check_PROGRAMS += \ if LINUX_HOST check_PROGRAMS += \ src/processor/disassembler_objdump_unittest \ + src/common/linux/scoped_pipe_unittest \ src/common/linux/scoped_tmpfile_unittest endif LINUX_HOST if SELFTEST @@ -558,6 +559,8 @@ src_client_linux_linux_client_unittest_shlib_SOURCES = \ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \ src/common/linux/elf_core_dump.cc \ src/common/linux/linux_libc_support_unittest.cc \ + src/common/linux/scoped_pipe.h \ + src/common/linux/scoped_pipe.cc \ src/common/linux/scoped_tmpfile.h \ src/common/linux/scoped_tmpfile.cc \ src/common/linux/tests/crash_generator.cc \ @@ -958,6 +961,15 @@ src_processor_exploitability_unittest_LDADD += \ src/processor/disassembler_objdump.o endif +src_common_linux_scoped_pipe_unittest_SOURCES = \ + src/common/linux/scoped_pipe_unittest.cc +src_common_linux_scoped_pipe_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) +src_common_linux_scoped_pipe_unittest_LDADD = \ + src/common/linux/scoped_pipe.o \ + $(TEST_LIBS) \ + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) + src_common_linux_scoped_tmpfile_unittest_SOURCES = \ src/common/linux/scoped_tmpfile_unittest.cc src_common_linux_scoped_tmpfile_unittest_CPPFLAGS = \ diff --git a/Makefile.in b/Makefile.in index 33e37458..ef7e8fe6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -194,6 +194,7 @@ EXTRA_PROGRAMS = $(am__EXEEXT_1) @DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@am__append_10 = \ @DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@ src/processor/disassembler_objdump_unittest \ +@DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@ src/common/linux/scoped_pipe_unittest \ @DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@ src/common/linux/scoped_tmpfile_unittest @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_11 = \ @@ -353,6 +354,7 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ @DISABLE_PROCESSOR_FALSE@ src/processor/stackwalker_x86_unittest$(EXEEXT) \ @DISABLE_PROCESSOR_FALSE@ src/processor/synth_minidump_unittest$(EXEEXT) @DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_6 = src/processor/disassembler_objdump_unittest$(EXEEXT) \ +@DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@ src/common/linux/scoped_pipe_unittest$(EXEEXT) \ @DISABLE_PROCESSOR_FALSE@@LINUX_HOST_TRUE@ src/common/linux/scoped_tmpfile_unittest$(EXEEXT) @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__EXEEXT_7 = src/processor/stackwalker_selftest$(EXEEXT) @LINUX_HOST_TRUE@am__EXEEXT_8 = src/client/linux/linux_client_unittest$(EXEEXT) \ @@ -674,6 +676,7 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \ src/common/linux/elf_core_dump.cc \ src/common/linux/linux_libc_support_unittest.cc \ + src/common/linux/scoped_pipe.h src/common/linux/scoped_pipe.cc \ src/common/linux/scoped_tmpfile.h \ src/common/linux/scoped_tmpfile.cc \ src/common/linux/tests/crash_generator.cc \ @@ -709,6 +712,7 @@ am_src_client_linux_linux_client_unittest_shlib_OBJECTS = \ src/client/linux/minidump_writer/linux_client_unittest_shlib-proc_cpuinfo_reader_unittest.$(OBJEXT) \ src/common/linux/client_linux_linux_client_unittest_shlib-elf_core_dump.$(OBJEXT) \ src/common/linux/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.$(OBJEXT) \ + src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.$(OBJEXT) \ src/common/linux/client_linux_linux_client_unittest_shlib-scoped_tmpfile.$(OBJEXT) \ src/common/linux/tests/client_linux_linux_client_unittest_shlib-crash_generator.$(OBJEXT) \ src/common/client_linux_linux_client_unittest_shlib-memory_allocator_unittest.$(OBJEXT) \ @@ -813,6 +817,12 @@ src_common_linux_google_crashdump_uploader_test_OBJECTS = \ src_common_linux_google_crashdump_uploader_test_DEPENDENCIES = \ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) +am_src_common_linux_scoped_pipe_unittest_OBJECTS = src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.$(OBJEXT) +src_common_linux_scoped_pipe_unittest_OBJECTS = \ + $(am_src_common_linux_scoped_pipe_unittest_OBJECTS) +src_common_linux_scoped_pipe_unittest_DEPENDENCIES = \ + src/common/linux/scoped_pipe.o $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_src_common_linux_scoped_tmpfile_unittest_OBJECTS = src/common/linux/scoped_tmpfile_unittest-scoped_tmpfile_unittest.$(OBJEXT) src_common_linux_scoped_tmpfile_unittest_OBJECTS = \ $(am_src_common_linux_scoped_tmpfile_unittest_OBJECTS) @@ -1531,6 +1541,7 @@ am__depfiles_remade = src/client/$(DEPDIR)/minidump_file_writer.Po \ src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po \ src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-elf_core_dump.Po \ src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po \ + src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po \ src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Po \ src/common/linux/$(DEPDIR)/dumper_unittest-crc32.Po \ src/common/linux/$(DEPDIR)/dumper_unittest-dump_symbols.Po \ @@ -1561,6 +1572,7 @@ am__depfiles_remade = src/client/$(DEPDIR)/minidump_file_writer.Po \ src/common/linux/$(DEPDIR)/linux_libc_support.Po \ src/common/linux/$(DEPDIR)/memory_mapped_file.Po \ src/common/linux/$(DEPDIR)/safe_readlink.Po \ + src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po \ src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Po \ src/common/linux/$(DEPDIR)/symbol_collector_client.Po \ src/common/linux/$(DEPDIR)/symbol_upload.Po \ @@ -1756,6 +1768,7 @@ SOURCES = $(src_client_linux_libbreakpad_client_a_SOURCES) \ $(src_common_dwarf_dwarf2reader_lineinfo_unittest_SOURCES) \ $(src_common_dwarf_dwarf2reader_splitfunctions_unittest_SOURCES) \ $(src_common_linux_google_crashdump_uploader_test_SOURCES) \ + $(src_common_linux_scoped_pipe_unittest_SOURCES) \ $(src_common_linux_scoped_tmpfile_unittest_SOURCES) \ $(src_common_mac_macho_reader_unittest_SOURCES) \ $(src_common_safe_math_unittest_SOURCES) \ @@ -1817,6 +1830,7 @@ DIST_SOURCES = \ $(src_common_dwarf_dwarf2reader_lineinfo_unittest_SOURCES) \ $(src_common_dwarf_dwarf2reader_splitfunctions_unittest_SOURCES) \ $(src_common_linux_google_crashdump_uploader_test_SOURCES) \ + $(src_common_linux_scoped_pipe_unittest_SOURCES) \ $(src_common_linux_scoped_tmpfile_unittest_SOURCES) \ $(src_common_mac_macho_reader_unittest_SOURCES) \ $(src_common_safe_math_unittest_SOURCES) \ @@ -2537,6 +2551,7 @@ src_client_linux_linux_client_unittest_shlib_SOURCES = \ src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \ src/common/linux/elf_core_dump.cc \ src/common/linux/linux_libc_support_unittest.cc \ + src/common/linux/scoped_pipe.h src/common/linux/scoped_pipe.cc \ src/common/linux/scoped_tmpfile.h \ src/common/linux/scoped_tmpfile.cc \ src/common/linux/tests/crash_generator.cc \ @@ -2927,6 +2942,17 @@ src_processor_exploitability_unittest_LDADD = \ src/processor/tokenize.o src/third_party/libdisasm/libdisasm.a \ $(TEST_LIBS) $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \ $(am__append_27) +src_common_linux_scoped_pipe_unittest_SOURCES = \ + src/common/linux/scoped_pipe_unittest.cc + +src_common_linux_scoped_pipe_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +src_common_linux_scoped_pipe_unittest_LDADD = \ + src/common/linux/scoped_pipe.o \ + $(TEST_LIBS) \ + $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) + src_common_linux_scoped_tmpfile_unittest_SOURCES = \ src/common/linux/scoped_tmpfile_unittest.cc @@ -4319,6 +4345,9 @@ src/common/linux/client_linux_linux_client_unittest_shlib-elf_core_dump.$(OBJEXT src/common/linux/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) +src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.$(OBJEXT): \ + src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) src/common/linux/client_linux_linux_client_unittest_shlib-scoped_tmpfile.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -4568,6 +4597,13 @@ src/common/linux/google_crashdump_uploader_test-libcurl_wrapper.$(OBJEXT): \ src/common/linux/google_crashdump_uploader_test$(EXEEXT): $(src_common_linux_google_crashdump_uploader_test_OBJECTS) $(src_common_linux_google_crashdump_uploader_test_DEPENDENCIES) $(EXTRA_src_common_linux_google_crashdump_uploader_test_DEPENDENCIES) src/common/linux/$(am__dirstamp) @rm -f src/common/linux/google_crashdump_uploader_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(src_common_linux_google_crashdump_uploader_test_OBJECTS) $(src_common_linux_google_crashdump_uploader_test_LDADD) $(LIBS) +src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.$(OBJEXT): \ + src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) + +src/common/linux/scoped_pipe_unittest$(EXEEXT): $(src_common_linux_scoped_pipe_unittest_OBJECTS) $(src_common_linux_scoped_pipe_unittest_DEPENDENCIES) $(EXTRA_src_common_linux_scoped_pipe_unittest_DEPENDENCIES) src/common/linux/$(am__dirstamp) + @rm -f src/common/linux/scoped_pipe_unittest$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(src_common_linux_scoped_pipe_unittest_OBJECTS) $(src_common_linux_scoped_pipe_unittest_LDADD) $(LIBS) src/common/linux/scoped_tmpfile_unittest-scoped_tmpfile_unittest.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -5365,6 +5401,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-elf_core_dump.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dumper_unittest-crc32.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dumper_unittest-dump_symbols.Po@am__quote@ # am--include-marker @@ -5395,6 +5432,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/linux_libc_support.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/memory_mapped_file.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/safe_readlink.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/symbol_collector_client.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/symbol_upload.Po@am__quote@ # am--include-marker @@ -5892,6 +5930,20 @@ src/common/linux/client_linux_linux_client_unittest_shlib-linux_libc_support_uni @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.obj `if test -f 'src/common/linux/linux_libc_support_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/linux_libc_support_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/linux_libc_support_unittest.cc'; fi` +src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.o: src/common/linux/scoped_pipe.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.o -MD -MP -MF src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Tpo -c -o src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.o `test -f 'src/common/linux/scoped_pipe.cc' || echo '$(srcdir)/'`src/common/linux/scoped_pipe.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Tpo src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/scoped_pipe.cc' object='src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.o `test -f 'src/common/linux/scoped_pipe.cc' || echo '$(srcdir)/'`src/common/linux/scoped_pipe.cc + +src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.obj: src/common/linux/scoped_pipe.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.obj -MD -MP -MF src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Tpo -c -o src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.obj `if test -f 'src/common/linux/scoped_pipe.cc'; then $(CYGPATH_W) 'src/common/linux/scoped_pipe.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/scoped_pipe.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Tpo src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/scoped_pipe.cc' object='src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/client_linux_linux_client_unittest_shlib-scoped_pipe.obj `if test -f 'src/common/linux/scoped_pipe.cc'; then $(CYGPATH_W) 'src/common/linux/scoped_pipe.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/scoped_pipe.cc'; fi` + src/common/linux/client_linux_linux_client_unittest_shlib-scoped_tmpfile.o: src/common/linux/scoped_tmpfile.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/client_linux_linux_client_unittest_shlib-scoped_tmpfile.o -MD -MP -MF src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Tpo -c -o src/common/linux/client_linux_linux_client_unittest_shlib-scoped_tmpfile.o `test -f 'src/common/linux/scoped_tmpfile.cc' || echo '$(srcdir)/'`src/common/linux/scoped_tmpfile.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Tpo src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Po @@ -6844,6 +6896,20 @@ src/common/linux/google_crashdump_uploader_test-libcurl_wrapper.obj: src/common/ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_google_crashdump_uploader_test_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/google_crashdump_uploader_test-libcurl_wrapper.obj `if test -f 'src/common/linux/libcurl_wrapper.cc'; then $(CYGPATH_W) 'src/common/linux/libcurl_wrapper.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/libcurl_wrapper.cc'; fi` +src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.o: src/common/linux/scoped_pipe_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_scoped_pipe_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Tpo -c -o src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.o `test -f 'src/common/linux/scoped_pipe_unittest.cc' || echo '$(srcdir)/'`src/common/linux/scoped_pipe_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Tpo src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/scoped_pipe_unittest.cc' object='src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_scoped_pipe_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.o `test -f 'src/common/linux/scoped_pipe_unittest.cc' || echo '$(srcdir)/'`src/common/linux/scoped_pipe_unittest.cc + +src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.obj: src/common/linux/scoped_pipe_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_scoped_pipe_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Tpo -c -o src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.obj `if test -f 'src/common/linux/scoped_pipe_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/scoped_pipe_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/scoped_pipe_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Tpo src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/scoped_pipe_unittest.cc' object='src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_scoped_pipe_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/scoped_pipe_unittest-scoped_pipe_unittest.obj `if test -f 'src/common/linux/scoped_pipe_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/scoped_pipe_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/scoped_pipe_unittest.cc'; fi` + src/common/linux/scoped_tmpfile_unittest-scoped_tmpfile_unittest.o: src/common/linux/scoped_tmpfile_unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_linux_scoped_tmpfile_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/scoped_tmpfile_unittest-scoped_tmpfile_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Tpo -c -o src/common/linux/scoped_tmpfile_unittest-scoped_tmpfile_unittest.o `test -f 'src/common/linux/scoped_tmpfile_unittest.cc' || echo '$(srcdir)/'`src/common/linux/scoped_tmpfile_unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Tpo src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Po @@ -9109,6 +9175,13 @@ src/processor/disassembler_objdump_unittest.log: src/processor/disassembler_objd --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +src/common/linux/scoped_pipe_unittest.log: src/common/linux/scoped_pipe_unittest$(EXEEXT) + @p='src/common/linux/scoped_pipe_unittest$(EXEEXT)'; \ + b='src/common/linux/scoped_pipe_unittest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) src/common/linux/scoped_tmpfile_unittest.log: src/common/linux/scoped_tmpfile_unittest$(EXEEXT) @p='src/common/linux/scoped_tmpfile_unittest$(EXEEXT)'; \ b='src/common/linux/scoped_tmpfile_unittest'; \ @@ -9608,6 +9681,7 @@ distclean: distclean-am -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-elf_core_dump.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po + -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Po -rm -f src/common/linux/$(DEPDIR)/dumper_unittest-crc32.Po -rm -f src/common/linux/$(DEPDIR)/dumper_unittest-dump_symbols.Po @@ -9638,6 +9712,7 @@ distclean: distclean-am -rm -f src/common/linux/$(DEPDIR)/linux_libc_support.Po -rm -f src/common/linux/$(DEPDIR)/memory_mapped_file.Po -rm -f src/common/linux/$(DEPDIR)/safe_readlink.Po + -rm -f src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po -rm -f src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Po -rm -f src/common/linux/$(DEPDIR)/symbol_collector_client.Po -rm -f src/common/linux/$(DEPDIR)/symbol_upload.Po @@ -9964,6 +10039,7 @@ maintainer-clean: maintainer-clean-am -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-elf_core_dump.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po + -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_pipe.Po -rm -f src/common/linux/$(DEPDIR)/client_linux_linux_client_unittest_shlib-scoped_tmpfile.Po -rm -f src/common/linux/$(DEPDIR)/dumper_unittest-crc32.Po -rm -f src/common/linux/$(DEPDIR)/dumper_unittest-dump_symbols.Po @@ -9994,6 +10070,7 @@ maintainer-clean: maintainer-clean-am -rm -f src/common/linux/$(DEPDIR)/linux_libc_support.Po -rm -f src/common/linux/$(DEPDIR)/memory_mapped_file.Po -rm -f src/common/linux/$(DEPDIR)/safe_readlink.Po + -rm -f src/common/linux/$(DEPDIR)/scoped_pipe_unittest-scoped_pipe_unittest.Po -rm -f src/common/linux/$(DEPDIR)/scoped_tmpfile_unittest-scoped_tmpfile_unittest.Po -rm -f src/common/linux/$(DEPDIR)/symbol_collector_client.Po -rm -f src/common/linux/$(DEPDIR)/symbol_upload.Po diff --git a/src/common/linux/scoped_pipe.cc b/src/common/linux/scoped_pipe.cc new file mode 100644 index 00000000..b13f8d45 --- /dev/null +++ b/src/common/linux/scoped_pipe.cc @@ -0,0 +1,128 @@ +// Copyright 2022 Google LLC +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (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 "common/linux/scoped_pipe.h" + +#include + +#include "common/linux/eintr_wrapper.h" + +namespace google_breakpad { + +ScopedPipe::ScopedPipe() { + fds_[0] = -1; + fds_[1] = -1; +} + +ScopedPipe::~ScopedPipe() { + CloseReadFd(); + CloseWriteFd(); +} + +bool ScopedPipe::Init() { + return pipe(fds_) == 0; +} + +void ScopedPipe::CloseReadFd() { + if (fds_[0] != -1) { + close(fds_[0]); + fds_[0] = -1; + } +} + +void ScopedPipe::CloseWriteFd() { + if (fds_[1] != -1) { + close(fds_[1]); + fds_[1] = -1; + } +} + +bool ScopedPipe::ReadLine(std::string& line) { + // Simple buffered file read. `read_buffer_` stores previously read bytes, and + // we either return a line from this buffer, or we append blocks of read bytes + // to the buffer until we have a complete line. + size_t eol_index = read_buffer_.find('\n'); + + // While we don't have a full line, and read pipe is valid. + while (eol_index == std::string::npos && GetReadFd() != -1) { + // Read a block of 128 bytes from the read pipe. + char read_buf[128]; + ssize_t read_len = HANDLE_EINTR( + read(GetReadFd(), read_buf, sizeof(read_buf))); + if (read_len <= 0) { + // Pipe error, or pipe has been closed. + CloseReadFd(); + break; + } + + // Append the block, and check if we have a full line now. + read_buffer_.append(read_buf, read_len); + eol_index = read_buffer_.find('\n'); + } + + if (eol_index != std::string::npos) { + // We have a full line to output. + line = read_buffer_.substr(0, eol_index); + if (eol_index < read_buffer_.size()) { + read_buffer_ = read_buffer_.substr(eol_index + 1); + } else { + read_buffer_ = ""; + } + + return true; + } + + if (read_buffer_.size()) { + // We don't have a full line to output, but we can only reach here if the + // pipe has closed and there are some bytes left at the end, so we should + // return those bytes. + line = std::move(read_buffer_); + read_buffer_ = ""; + + return true; + } + + // We don't have any buffered data left, and the pipe has closed. + return false; +} + +int ScopedPipe::Dup2WriteFd(int new_fd) const { + return dup2(fds_[1], new_fd); +} + +bool ScopedPipe::WriteForTesting(const void* bytes, size_t bytes_len) { + ssize_t r = HANDLE_EINTR(write(GetWriteFd(), bytes, bytes_len)); + if (r != static_cast(bytes_len)) { + CloseWriteFd(); + return false; + } + + return true; +} + +} // namespace google_breakpad diff --git a/src/common/linux/scoped_pipe.h b/src/common/linux/scoped_pipe.h new file mode 100644 index 00000000..25394c2a --- /dev/null +++ b/src/common/linux/scoped_pipe.h @@ -0,0 +1,115 @@ +// Copyright 2022 Google LLC +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef COMMON_LINUX_SCOPED_PIPE_H_ +#define COMMON_LINUX_SCOPED_PIPE_H_ + +#include +#include + +namespace google_breakpad { + +// Small RAII wrapper for a pipe pair. +// +// Example (both ends of pipe in same process): +// ScopedPipe tmp; +// std::string line; +// if (tmp.Init() && tmp.Write(bytes, bytes_len)) { +// tmp.CloseWriteFd(); +// while (tmp.ReadLine(&line)) { +// std::cerr << line << std::endl; +// } +// } +// +// Example (reading output from a child process): +// ScopedPipe tmp; +// if (fork()) { +// // Parent process, read from the read end of the pipe. +// std::string line; +// while (tmp.ReadLine(line)) { +// // Process output... +// } +// // Close read pipe once done processing the output that we wanted, this +// // should ensure that the child process exits even if we didn't read all +// // of the output. +// tmp.CloseReadFd(); +// // Parent process should handle waiting for child to exit here... +// } else { +// // Child process, close the read fd and dup the write fd before exec'ing. +// tmp.CloseReadFd(); +// tmp.Dup2WriteFd(STDOUT_FILENO); +// tmp.Dup2WriteFd(STDERR_FILENO); +// execl("some-command", "some-arguments"); +// } +class ScopedPipe { + public: + ScopedPipe(); + ~ScopedPipe(); + + // Creates the pipe pair - returns false on error. + bool Init(); + + // Close the read pipe. This only needs to be used when the read pipe needs to + // be closed earlier. + void CloseReadFd(); + + // Close the write pipe. This only needs to be used when the write pipe needs + // to be closed earlier. + void CloseWriteFd(); + + // Reads characters until newline or end of pipe. On read failure this will + // close the read pipe, but continue to return true and read buffered lines + // until the internal buffering is exhausted. This will block if there is no + // data available on the read pipe. + bool ReadLine(std::string& line); + + // Writes bytes to the write end of the pipe, returns false and closes write + // pipe on failure. + bool WriteForTesting(const void* bytes, size_t bytes_len); + + // Calls the dup2 system call to replace any existing open file descriptor + // with number new_fd with a copy of the current write end file descriptor + // for the pipe. + int Dup2WriteFd(int new_fd) const; + + private: + int GetReadFd() const { + return fds_[0]; + } + + int GetWriteFd() const { + return fds_[1]; + } + + int fds_[2]; + std::string read_buffer_; +}; + +} // namespace google_breakpad + +#endif // COMMON_LINUX_SCOPED_PIPE_H_ diff --git a/src/common/linux/scoped_pipe_unittest.cc b/src/common/linux/scoped_pipe_unittest.cc new file mode 100644 index 00000000..a7d6272c --- /dev/null +++ b/src/common/linux/scoped_pipe_unittest.cc @@ -0,0 +1,71 @@ +// Copyright 2022 Google LLC +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// scoped_pipe_unittest.cc: Unit tests for google_breakpad::ScopedPipe. + +#include "common/linux/scoped_pipe.h" + +#include "breakpad_googletest_includes.h" + +namespace google_breakpad { + +TEST(ScopedPipeTest, WriteAndClose) { + const char kTestData[] = "One\nTwo\nThree"; + ScopedPipe pipe; + std::string line; + + ASSERT_TRUE(pipe.Init()); + ASSERT_TRUE(pipe.WriteForTesting(kTestData, strlen(kTestData))); + pipe.CloseWriteFd(); + + ASSERT_TRUE(pipe.ReadLine(line)); + ASSERT_EQ(line, "One"); + ASSERT_TRUE(pipe.ReadLine(line)); + ASSERT_EQ(line, "Two"); + ASSERT_TRUE(pipe.ReadLine(line)); + ASSERT_EQ(line, "Three"); + ASSERT_FALSE(pipe.ReadLine(line)); +} + +TEST(ScopedPipeTest, MultipleWrites) { + const char kTestDataOne[] = "One\n"; + const char kTestDataTwo[] = "Two\n"; + ScopedPipe pipe; + std::string line; + + ASSERT_TRUE(pipe.Init()); + ASSERT_TRUE(pipe.WriteForTesting(kTestDataOne, strlen(kTestDataOne))); + ASSERT_TRUE(pipe.ReadLine(line)); + ASSERT_EQ(line, "One"); + + ASSERT_TRUE(pipe.WriteForTesting(kTestDataTwo, strlen(kTestDataTwo))); + ASSERT_TRUE(pipe.ReadLine(line)); + ASSERT_EQ(line, "Two"); +} + +} // namespace google_breakpad