[1/6] Introduce scoped_pipe.h

Message ID 20200226200542.746617-2-sergiodj@redhat.com
State New, archived
Headers

Commit Message

Sergio Durigan Junior Feb. 26, 2020, 8:05 p.m. UTC
  This simple patch introduces gdbsupport/scoped_pipe.h, which is based
on gdbsupport/scoped_fd.h.  When the object is instantiated, a pipe is
created using 'gdb_pipe_cloexec'.  There are two methods (get_read_end
and get_write_end) that allow the user to obtain the read/write ends
of the pipe (no more messing with [0] and [1]), and when the object is
destroyed, the pipe is closed (both ends).

gdb/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* unittests/scoped_pipe-selftests.c: New file.

gdbsupport/ChangeLog:
yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

	* scoped_pipe.h: New file.
---
 gdb/Makefile.in                       |  1 +
 gdb/unittests/scoped_pipe-selftests.c | 96 +++++++++++++++++++++++++++
 gdbsupport/scoped_pipe.h              | 63 ++++++++++++++++++
 3 files changed, 160 insertions(+)
 create mode 100644 gdb/unittests/scoped_pipe-selftests.c
 create mode 100644 gdbsupport/scoped_pipe.h
  

Comments

Tom Tromey Feb. 28, 2020, 3:23 p.m. UTC | #1
>>>>> "Sergio" == Sergio Durigan Junior <sergiodj@redhat.com> writes:

Sergio> gdb/ChangeLog:
Sergio> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

Sergio> 	* unittests/scoped_pipe-selftests.c: New file.

Sergio> gdbsupport/ChangeLog:
Sergio> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>

Sergio> 	* scoped_pipe.h: New file.

I think new general-purpose code should go in gdbsupport.

Unfortunately right now we don't have a good way to put the unit tests
there.  This is something we ought to do eventually though.

Sergio> +#ifndef COMMON_SCOPED_PIPE_H

I think we've been using GDBSUPPORT rather than COMMON now.

Sergio> +  explicit scoped_pipe ()

I think explicit is only needed for 1-arg constructors.

Tom
  
Sergio Durigan Junior Feb. 28, 2020, 4:08 p.m. UTC | #2
On Friday, February 28 2020, Tom Tromey wrote:

>>>>>> "Sergio" == Sergio Durigan Junior <sergiodj@redhat.com> writes:
>
> Sergio> gdb/ChangeLog:
> Sergio> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> Sergio> 	* unittests/scoped_pipe-selftests.c: New file.
>
> Sergio> gdbsupport/ChangeLog:
> Sergio> yyyy-mm-dd  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> Sergio> 	* scoped_pipe.h: New file.
>
> I think new general-purpose code should go in gdbsupport.

Yep.  scoped_pipe.h is there.

> Unfortunately right now we don't have a good way to put the unit tests
> there.  This is something we ought to do eventually though.

Right, that's something I noticed as well.

> Sergio> +#ifndef COMMON_SCOPED_PIPE_H
>
> I think we've been using GDBSUPPORT rather than COMMON now.

Ah, OK.  I found other places using COMMON, but I'll change it here.

> Sergio> +  explicit scoped_pipe ()
>
> I think explicit is only needed for 1-arg constructors.

OK, I'll remove the keyword.

I'll make the changes locally.

Thanks,
  
Tom Tromey Feb. 28, 2020, 6:57 p.m. UTC | #3
>> I think new general-purpose code should go in gdbsupport.

Sergio> Yep.  scoped_pipe.h is there.

Lol, sorry about that.

Tom
  
Pedro Alves Feb. 28, 2020, 7:19 p.m. UTC | #4
On 2/26/20 8:05 PM, Sergio Durigan Junior wrote:

> --- /dev/null
> +++ b/gdb/unittests/scoped_pipe-selftests.c
> @@ -0,0 +1,96 @@

> +
> +#include "defs.h"
> +
> +#include "gdbsupport/scoped_pipe.h"
> +#include "config.h"

Was there a reason for this "config.h" include?

Pedro Alves
  
Sergio Durigan Junior Feb. 28, 2020, 7:47 p.m. UTC | #5
On Friday, February 28 2020, Pedro Alves wrote:

> On 2/26/20 8:05 PM, Sergio Durigan Junior wrote:
>
>> --- /dev/null
>> +++ b/gdb/unittests/scoped_pipe-selftests.c
>> @@ -0,0 +1,96 @@
>
>> +
>> +#include "defs.h"
>> +
>> +#include "gdbsupport/scoped_pipe.h"
>> +#include "config.h"
>
> Was there a reason for this "config.h" include?

I copied this test from the existing scoped_fd-selftests.c and adjusted
it.  I did remove other includes, but left this one untouched.  I tried
removing it now, and the file builds just fine, so I'll update my copy
of the patch here.  Thanks!
  
Sergio Durigan Junior Feb. 28, 2020, 7:48 p.m. UTC | #6
On Friday, February 28 2020, Tom Tromey wrote:

>>> I think new general-purpose code should go in gdbsupport.
>
> Sergio> Yep.  scoped_pipe.h is there.
>
> Lol, sorry about that.

That's alright!  I was confused with your comment, but wasn't sure if
you meant something else by it ;-).
  
Pedro Alves Feb. 28, 2020, 8:07 p.m. UTC | #7
On 2/28/20 7:47 PM, Sergio Durigan Junior wrote:
> On Friday, February 28 2020, Pedro Alves wrote:
> 
>> On 2/26/20 8:05 PM, Sergio Durigan Junior wrote:
>>

>>> --- /dev/null
>>> +++ b/gdb/unittests/scoped_pipe-selftests.c
>>> @@ -0,0 +1,96 @@
>>
>>> +
>>> +#include "defs.h"
>>> +
>>> +#include "gdbsupport/scoped_pipe.h"
>>> +#include "config.h"
>>
>> Was there a reason for this "config.h" include?
> 
> I copied this test from the existing scoped_fd-selftests.c and adjusted
> it.  I did remove other includes, but left this one untouched.  I tried
> removing it now, and the file builds just fine, so I'll update my copy
> of the patch here.  Thanks!

Ah, I see.  That config.h include shouldn't be there in
scoped_fd-selftests.c either.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index f9606b8fc7..d5f1450035 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -444,6 +444,7 @@  SUBDIR_UNITTESTS_SRCS = \
 	unittests/rsp-low-selftests.c \
 	unittests/scoped_fd-selftests.c \
 	unittests/scoped_mmap-selftests.c \
+	unittests/scoped_pipe-selftests.c \
 	unittests/scoped_restore-selftests.c \
 	unittests/string_view-selftests.c \
 	unittests/style-selftests.c \
diff --git a/gdb/unittests/scoped_pipe-selftests.c b/gdb/unittests/scoped_pipe-selftests.c
new file mode 100644
index 0000000000..dd634bec97
--- /dev/null
+++ b/gdb/unittests/scoped_pipe-selftests.c
@@ -0,0 +1,96 @@ 
+/* Self tests for scoped_pipe for GDB, the GNU debugger.
+
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+
+#include "gdbsupport/scoped_pipe.h"
+#include "config.h"
+#include "gdbsupport/selftest.h"
+
+namespace selftests {
+namespace scoped_pipe {
+
+/* Test that the pipe is correctly created.  */
+
+static void
+test_create ()
+{
+  ::scoped_pipe spipe;
+
+  SELF_CHECK (spipe.get_read_end () > 0);
+  SELF_CHECK (spipe.get_write_end () > 0);
+}
+
+/* Test that we can write and read from the pipe.  */
+
+static void
+test_transmission ()
+{
+  int foo = 123;
+  ::scoped_pipe spipe;
+
+  /* Write to the pipe.  */
+  {
+    ssize_t writeret;
+
+    do
+      {
+	writeret = write (spipe.get_write_end (), &foo, sizeof (foo));
+      }
+    while (writeret < 0 && (errno == EAGAIN || errno == EINTR));
+
+    SELF_CHECK (writeret > 0);
+  }
+
+  /* Read from the pipe, and check if the value read is the same as
+     the one that was written.  */
+  {
+    ssize_t readret;
+    int read_foo;
+
+    do
+      {
+	readret = read (spipe.get_read_end (), &read_foo, sizeof (read_foo));
+      }
+    while (readret < 0 && (errno == EAGAIN || errno == EINTR));
+
+    SELF_CHECK (readret > 0);
+
+    SELF_CHECK (read_foo == foo);
+  }
+}
+
+/* Run selftests.  */
+static void
+run_tests ()
+{
+  test_create ();
+  test_transmission ();
+}
+
+} /* namespace scoped_pipe */
+} /* namespace selftests */
+
+void _initialize_scoped_pipe_selftests ();
+void
+_initialize_scoped_pipe_selftests ()
+{
+  selftests::register_test ("scoped_pipe",
+			    selftests::scoped_pipe::run_tests);
+}
diff --git a/gdbsupport/scoped_pipe.h b/gdbsupport/scoped_pipe.h
new file mode 100644
index 0000000000..8f133b442f
--- /dev/null
+++ b/gdbsupport/scoped_pipe.h
@@ -0,0 +1,63 @@ 
+/* scoped_pipe, automatically close a pipe.
+
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef COMMON_SCOPED_PIPE_H
+#define COMMON_SCOPED_PIPE_H
+
+#include <unistd.h>
+#include "filestuff.h"
+
+/* A smart-pointer-like class to automatically close a pipe.  */
+
+class scoped_pipe
+{
+public:
+  explicit scoped_pipe ()
+  {
+    if (gdb_pipe_cloexec (m_pipe) < 0)
+      error (_("gdb_pipe_cloexec: %s"), safe_strerror (errno));
+  }
+
+  ~scoped_pipe ()
+  {
+    if (m_pipe[0] >= 0)
+      close (m_pipe[0]);
+    if (m_pipe[1] >= 0)
+      close (m_pipe[1]);
+  }
+
+  DISABLE_COPY_AND_ASSIGN (scoped_pipe);
+
+  /* Get the read end of the pipe.  */
+  int get_read_end () const noexcept
+  {
+    return m_pipe[0];
+  }
+
+  /* Get the write end of the pipe.  */
+  int get_write_end () const noexcept
+  {
+    return m_pipe[1];
+  }
+
+private:
+  int m_pipe[2];
+};
+
+#endif /* ! COMMON_SCOPED_PIPE_H */