Patchwork [RFA,v3,02/23] Introduce and use gdb_file_up

login
register
mail settings
Submitter Tom Tromey
Date Aug. 2, 2017, 3:02 p.m.
Message ID <20170802150227.24460-3-tom@tromey.com>
Download mbox | patch
Permalink /patch/21866/
State New
Headers show

Comments

Tom Tromey - Aug. 2, 2017, 3:02 p.m.
This introduces gdb_file_up, a unique pointer holding a FILE*, and
then changes some code in gdb to use it.  In particular
gdb_fopen_cloexec now returns a gdb_file_up.  This allow removing some
cleanups.

ChangeLog
2017-08-02  Tom Tromey  <tom@tromey.com>

	* xml-support.c (xml_fetch_content_from_file): Update.
	* ui-file.c (stdio_file::open): Update.
	* tracefile-tfile.c (tfile_start): Update.
	* remote.c (remote_file_put, remote_file_get): Update.
	* nat/linux-procfs.c (linux_proc_get_int)
	(linux_proc_pid_get_state, linux_proc_tid_get_name): Update.
	* nat/linux-osdata.c (linux_common_core_of_thread): Update.
	(command_from_pid, commandline_from_pid, linux_xfer_osdata_cpus)
	(print_sockets, linux_xfer_osdata_shm, linux_xfer_osdata_sem)
	(linux_xfer_osdata_msg, linux_xfer_osdata_modules): Update.
	* nat/linux-btrace.c (linux_determine_kernel_start): Update.
	* linux-nat.c (linux_proc_pending_signals): Update.
	* dwarf2read.c (write_psymtabs_to_index): Use gdb_file_up.
	(file_closer): Remove.
	* compile/compile.c (compile_to_object): Update.
	* common/filestuff.h (struct gdb_file_deleter): New.
	(gdb_file_up): New typedef.
	(gdb_fopen_cloexec): Change return type.
	* common/filestuff.c (gdb_fopen_cloexec): Return gdb_file_up.
	* cli/cli-dump.c (fopen_with_cleanup): Remove.
	(dump_binary_file, restore_binary_file): Update.
	* auto-load.c (auto_load_objfile_script_1): Update.
---
 gdb/ChangeLog          | 25 ++++++++++++++++
 gdb/auto-load.c        |  7 ++---
 gdb/cli/cli-dump.c     | 28 +++++-------------
 gdb/common/filestuff.c |  4 +--
 gdb/common/filestuff.h | 15 +++++++++-
 gdb/compile/compile.c  | 17 +++++------
 gdb/dwarf2read.c       | 18 ++----------
 gdb/linux-nat.c        |  9 ++----
 gdb/nat/linux-btrace.c |  9 ++----
 gdb/nat/linux-osdata.c | 78 ++++++++++++++++----------------------------------
 gdb/nat/linux-procfs.c | 18 ++++--------
 gdb/remote.c           | 18 +++++-------
 gdb/tracefile-tfile.c  |  2 +-
 gdb/ui-file.c          |  4 +--
 gdb/xml-support.c      | 13 ++++-----
 15 files changed, 112 insertions(+), 153 deletions(-)

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 940eaa6..6a25f2b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,30 @@ 
 2017-08-02  Tom Tromey  <tom@tromey.com>
 
+	* xml-support.c (xml_fetch_content_from_file): Update.
+	* ui-file.c (stdio_file::open): Update.
+	* tracefile-tfile.c (tfile_start): Update.
+	* remote.c (remote_file_put, remote_file_get): Update.
+	* nat/linux-procfs.c (linux_proc_get_int)
+	(linux_proc_pid_get_state, linux_proc_tid_get_name): Update.
+	* nat/linux-osdata.c (linux_common_core_of_thread): Update.
+	(command_from_pid, commandline_from_pid, linux_xfer_osdata_cpus)
+	(print_sockets, linux_xfer_osdata_shm, linux_xfer_osdata_sem)
+	(linux_xfer_osdata_msg, linux_xfer_osdata_modules): Update.
+	* nat/linux-btrace.c (linux_determine_kernel_start): Update.
+	* linux-nat.c (linux_proc_pending_signals): Update.
+	* dwarf2read.c (write_psymtabs_to_index): Use gdb_file_up.
+	(file_closer): Remove.
+	* compile/compile.c (compile_to_object): Update.
+	* common/filestuff.h (struct gdb_file_deleter): New.
+	(gdb_file_up): New typedef.
+	(gdb_fopen_cloexec): Change return type.
+	* common/filestuff.c (gdb_fopen_cloexec): Return gdb_file_up.
+	* cli/cli-dump.c (fopen_with_cleanup): Remove.
+	(dump_binary_file, restore_binary_file): Update.
+	* auto-load.c (auto_load_objfile_script_1): Update.
+
+2017-08-02  Tom Tromey  <tom@tromey.com>
+
 	* tracepoint.c (tvariables_info_1): Use ui_out_emit_table.
 	(info_static_tracepoint_markers_command): Likewise.
 	* solib.c (info_sharedlibrary_command): Use ui_out_emit_table.
diff --git a/gdb/auto-load.c b/gdb/auto-load.c
index 75ce828..292f2ae 100644
--- a/gdb/auto-load.c
+++ b/gdb/auto-load.c
@@ -786,7 +786,6 @@  auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
 {
   char *filename, *debugfile;
   int len, retval;
-  FILE *input;
   struct cleanup *cleanups;
   const char *suffix = ext_lang_auto_load_suffix (language);
 
@@ -797,7 +796,7 @@  auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
 
   cleanups = make_cleanup (xfree, filename);
 
-  input = gdb_fopen_cloexec (filename, "r");
+  gdb_file_up input = gdb_fopen_cloexec (filename, "r");
   debugfile = filename;
   if (debug_auto_load)
     fprintf_unfiltered (gdb_stdlog, _("auto-load: Attempted file \"%s\" %s.\n"),
@@ -845,8 +844,6 @@  auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
       int is_safe;
       struct auto_load_pspace_info *pspace_info;
 
-      make_cleanup_fclose (input);
-
       is_safe
 	= file_is_auto_load_safe (debugfile,
 				  _("auto-load: Loading %s script \"%s\""
@@ -875,7 +872,7 @@  auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
 	     compiled in.  And the extension language is required to implement
 	     this function.  */
 	  gdb_assert (sourcer != NULL);
-	  sourcer (language, objfile, input, debugfile);
+	  sourcer (language, objfile, input.get (), debugfile);
 	}
 
       retval = 1;
diff --git a/gdb/cli/cli-dump.c b/gdb/cli/cli-dump.c
index d6d4aab..3d8d386 100644
--- a/gdb/cli/cli-dump.c
+++ b/gdb/cli/cli-dump.c
@@ -92,17 +92,6 @@  scan_filename_with_cleanup (const char **cmd, const char *defname)
   return fullname;
 }
 
-static FILE *
-fopen_with_cleanup (const char *filename, const char *mode)
-{
-  FILE *file = gdb_fopen_cloexec (filename, mode);
-
-  if (file == NULL)
-    perror_with_name (filename);
-  make_cleanup_fclose (file);
-  return file;
-}
-
 static gdb_bfd_ref_ptr
 bfd_openr_or_error (const char *filename, const char *target)
 {
@@ -168,11 +157,10 @@  static void
 dump_binary_file (const char *filename, const char *mode, 
 		  const bfd_byte *buf, ULONGEST len)
 {
-  FILE *file;
   int status;
 
-  file = fopen_with_cleanup (filename, mode);
-  status = fwrite (buf, len, 1, file);
+  gdb_file_up file = gdb_fopen_cloexec (filename, mode);
+  status = fwrite (buf, len, 1, file.get ());
   if (status != 1)
     perror_with_name (filename);
 }
@@ -509,14 +497,13 @@  restore_section_callback (bfd *ibfd, asection *isec, void *args)
 static void
 restore_binary_file (const char *filename, struct callback_data *data)
 {
-  struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
-  FILE *file = fopen_with_cleanup (filename, FOPEN_RB);
+  gdb_file_up file = gdb_fopen_cloexec (filename, FOPEN_RB);
   long len;
 
   /* Get the file size for reading.  */
-  if (fseek (file, 0, SEEK_END) == 0)
+  if (fseek (file.get (), 0, SEEK_END) == 0)
     {
-      len = ftell (file);
+      len = ftell (file.get ());
       if (len < 0)
 	perror_with_name (filename);
     }
@@ -541,12 +528,12 @@  restore_binary_file (const char *filename, struct callback_data *data)
      (unsigned long) (data->load_start + data->load_offset + len));
 
   /* Now set the file pos to the requested load start pos.  */
-  if (fseek (file, data->load_start, SEEK_SET) != 0)
+  if (fseek (file.get (), data->load_start, SEEK_SET) != 0)
     perror_with_name (filename);
 
   /* Now allocate a buffer and read the file contents.  */
   gdb::byte_vector buf (len);
-  if (fread (buf.data (), 1, len, file) != len)
+  if (fread (buf.data (), 1, len, file.get ()) != len)
     perror_with_name (filename);
 
   /* Now write the buffer into target memory.  */
@@ -554,7 +541,6 @@  restore_binary_file (const char *filename, struct callback_data *data)
 			     buf.data (), len);
   if (len != 0)
     warning (_("restore: memory write failed (%s)."), safe_strerror (len));
-  do_cleanups (cleanup);
 }
 
 static void
diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c
index 725fb92..4b05884 100644
--- a/gdb/common/filestuff.c
+++ b/gdb/common/filestuff.c
@@ -300,7 +300,7 @@  gdb_open_cloexec (const char *filename, int flags, unsigned long mode)
 
 /* See filestuff.h.  */
 
-FILE *
+gdb_file_up
 gdb_fopen_cloexec (const char *filename, const char *opentype)
 {
   FILE *result;
@@ -336,7 +336,7 @@  gdb_fopen_cloexec (const char *filename, const char *opentype)
   if (result != NULL)
     maybe_mark_cloexec (fileno (result));
 
-  return result;
+  return gdb_file_up (result);
 }
 
 #ifdef HAVE_SOCKETS
diff --git a/gdb/common/filestuff.h b/gdb/common/filestuff.h
index b0a811b..3cf2df6 100644
--- a/gdb/common/filestuff.h
+++ b/gdb/common/filestuff.h
@@ -46,10 +46,23 @@  extern void close_most_fds (void);
 extern int gdb_open_cloexec (const char *filename, int flags,
 			     /* mode_t */ unsigned long mode);
 
+struct gdb_file_deleter
+{
+  void operator() (FILE *file) const
+  {
+    fclose (file);
+  }
+};
+
+/* A unique pointer to a FILE.  */
+
+typedef std::unique_ptr<FILE, gdb_file_deleter> gdb_file_up;
+
 /* Like 'fopen', but ensures that the returned file descriptor has the
    close-on-exec flag set.  */
 
-extern FILE *gdb_fopen_cloexec (const char *filename, const char *opentype);
+extern gdb_file_up gdb_fopen_cloexec (const char *filename,
+				      const char *opentype);
 
 /* Like 'socketpair', but ensures that the returned file descriptors
    have the close-on-exec flag set.  */
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index 1771692..d8c505f 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -547,14 +547,15 @@  compile_to_object (struct command_line *cmd, const char *cmd_string,
 
   compile_file_names fnames = get_new_file_names ();
 
-  src = gdb_fopen_cloexec (fnames.source_file (), "w");
-  if (src == NULL)
-    perror_with_name (_("Could not open source file for writing"));
-  inner_cleanup = make_cleanup (cleanup_unlink_file,
-				(void *) fnames.source_file ());
-  if (fputs (code.c_str (), src) == EOF)
-    perror_with_name (_("Could not write to source file"));
-  fclose (src);
+  {
+    gdb_file_up src = gdb_fopen_cloexec (fnames.source_file (), "w");
+    if (src == NULL)
+      perror_with_name (_("Could not open source file for writing"));
+    inner_cleanup = make_cleanup (cleanup_unlink_file,
+				  (void *) fnames.source_file ());
+    if (fputs (code.c_str (), src.get ()) == EOF)
+      perror_with_name (_("Could not write to source file"));
+  }
 
   if (compile_debug)
     fprintf_unfiltered (gdb_stdlog, "source file produced: %s\n\n",
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2c2ecda..fae3b62 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -23780,20 +23780,6 @@  recursively_write_psymbols (struct objfile *objfile,
 		  1);
 }
 
-/* Closes FILE on scope exit.  */
-struct file_closer
-{
-  explicit file_closer (FILE *file)
-    : m_file (file)
-  {}
-
-  ~file_closer ()
-  { fclose (m_file); }
-
-private:
-  FILE *m_file;
-};
-
 /* Create an index file for OBJFILE in the directory DIR.  */
 
 static void
@@ -23815,7 +23801,7 @@  write_psymtabs_to_index (struct objfile *objfile, const char *dir)
   std::string filename (std::string (dir) + SLASH_STRING
 			+ lbasename (objfile_name (objfile)) + INDEX_SUFFIX);
 
-  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb");
+  FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
   if (!out_file)
     error (_("Can't open `%s' for writing"), filename.c_str ());
 
@@ -23824,7 +23810,7 @@  write_psymtabs_to_index (struct objfile *objfile, const char *dir)
      still open.  (Don't call anything here that might throw until
      file_closer is created.)  */
   gdb::unlinker unlink_file (filename.c_str ());
-  file_closer close_out_file (out_file);
+  gdb_file_up close_out_file (out_file);
 
   mapped_symtab symtab;
   data_buf cu_list;
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 8b29245..b9c7d1f 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4187,20 +4187,17 @@  void
 linux_proc_pending_signals (int pid, sigset_t *pending,
 			    sigset_t *blocked, sigset_t *ignored)
 {
-  FILE *procfile;
   char buffer[PATH_MAX], fname[PATH_MAX];
-  struct cleanup *cleanup;
 
   sigemptyset (pending);
   sigemptyset (blocked);
   sigemptyset (ignored);
   xsnprintf (fname, sizeof fname, "/proc/%d/status", pid);
-  procfile = gdb_fopen_cloexec (fname, "r");
+  gdb_file_up procfile = gdb_fopen_cloexec (fname, "r");
   if (procfile == NULL)
     error (_("Could not open %s"), fname);
-  cleanup = make_cleanup_fclose (procfile);
 
-  while (fgets (buffer, PATH_MAX, procfile) != NULL)
+  while (fgets (buffer, PATH_MAX, procfile.get ()) != NULL)
     {
       /* Normal queued signals are on the SigPnd line in the status
 	 file.  However, 2.6 kernels also have a "shared" pending
@@ -4219,8 +4216,6 @@  linux_proc_pending_signals (int pid, sigset_t *pending,
       else if (startswith (buffer, "SigIgn:\t"))
 	add_line_to_sigset (buffer + 8, ignored);
     }
-
-  do_cleanups (cleanup);
 }
 
 static enum target_xfer_status
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index b2c84c1..1a383b7 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -204,24 +204,23 @@  linux_determine_kernel_start (void)
 {
   static uint64_t kernel_start;
   static int cached;
-  FILE *file;
 
   if (cached != 0)
     return kernel_start;
 
   cached = 1;
 
-  file = gdb_fopen_cloexec ("/proc/kallsyms", "r");
+  gdb_file_up file = gdb_fopen_cloexec ("/proc/kallsyms", "r");
   if (file == NULL)
     return kernel_start;
 
-  while (!feof (file))
+  while (!feof (file.get ()))
     {
       char buffer[1024], symbol[8], *line;
       uint64_t addr;
       int match;
 
-      line = fgets (buffer, sizeof (buffer), file);
+      line = fgets (buffer, sizeof (buffer), file.get ());
       if (line == NULL)
 	break;
 
@@ -236,8 +235,6 @@  linux_determine_kernel_start (void)
 	}
     }
 
-  fclose (file);
-
   return kernel_start;
 }
 
diff --git a/gdb/nat/linux-osdata.c b/gdb/nat/linux-osdata.c
index ba2e5a5..4b40a4d 100644
--- a/gdb/nat/linux-osdata.c
+++ b/gdb/nat/linux-osdata.c
@@ -61,7 +61,6 @@  int
 linux_common_core_of_thread (ptid_t ptid)
 {
   char filename[sizeof ("/proc//task//stat") + 2 * MAX_PID_T_STRLEN];
-  FILE *f;
   char *content = NULL;
   char *p;
   char *ts = 0;
@@ -71,7 +70,7 @@  linux_common_core_of_thread (ptid_t ptid)
 
   sprintf (filename, "/proc/%lld/task/%lld/stat",
 	   (PID_T) ptid_get_pid (ptid), (PID_T) ptid_get_lwp (ptid));
-  f = gdb_fopen_cloexec (filename, "r");
+  gdb_file_up f = gdb_fopen_cloexec (filename, "r");
   if (!f)
     return -1;
 
@@ -79,7 +78,7 @@  linux_common_core_of_thread (ptid_t ptid)
     {
       int n;
       content = (char *) xrealloc (content, content_read + 1024);
-      n = fread (content + content_read, 1, 1024, f);
+      n = fread (content + content_read, 1, 1024, f.get ());
       content_read += n;
       if (n < 1024)
 	{
@@ -104,7 +103,6 @@  linux_common_core_of_thread (ptid_t ptid)
     core = -1;
 
   xfree (content);
-  fclose (f);
 
   return core;
 }
@@ -117,7 +115,7 @@  static void
 command_from_pid (char *command, int maxlen, PID_T pid)
 {
   char *stat_path = xstrprintf ("/proc/%lld/stat", pid); 
-  FILE *fp = gdb_fopen_cloexec (stat_path, "r");
+  gdb_file_up fp = gdb_fopen_cloexec (stat_path, "r");
   
   command[0] = '\0';
  
@@ -128,15 +126,13 @@  command_from_pid (char *command, int maxlen, PID_T pid)
 	 (for the brackets).  */
       char cmd[18];
       PID_T stat_pid;
-      int items_read = fscanf (fp, "%lld %17s", &stat_pid, cmd);
+      int items_read = fscanf (fp.get (), "%lld %17s", &stat_pid, cmd);
 	  
       if (items_read == 2 && pid == stat_pid)
 	{
 	  cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis.  */
 	  strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis.  */
 	}
-
-      fclose (fp);
     }
   else
     {
@@ -157,16 +153,16 @@  commandline_from_pid (PID_T pid)
 {
   char *pathname = xstrprintf ("/proc/%lld/cmdline", pid);
   char *commandline = NULL;
-  FILE *f = gdb_fopen_cloexec (pathname, "r");
+  gdb_file_up f = gdb_fopen_cloexec (pathname, "r");
 
   if (f)
     {
       size_t len = 0;
 
-      while (!feof (f))
+      while (!feof (f.get ()))
 	{
 	  char buf[1024];
-	  size_t read_bytes = fread (buf, 1, sizeof (buf), f);
+	  size_t read_bytes = fread (buf, 1, sizeof (buf), f.get ());
      
 	  if (read_bytes)
 	    {
@@ -176,8 +172,6 @@  commandline_from_pid (PID_T pid)
 	    }
 	}
 
-      fclose (f);
-
       if (commandline)
 	{
 	  size_t i;
@@ -675,7 +669,6 @@  linux_xfer_osdata_cpus (gdb_byte *readbuf,
 
   if (offset == 0)
     {
-      FILE *fp;
       int first_item = 1;
 
       if (len_avail != -1 && len_avail != 0)
@@ -685,14 +678,14 @@  linux_xfer_osdata_cpus (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"cpus\">\n");
 
-      fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
+      gdb_file_up fp = gdb_fopen_cloexec ("/proc/cpuinfo", "r");
       if (fp != NULL)
 	{
 	  char buf[8192];
 
 	  do
 	    {
-	      if (fgets (buf, sizeof (buf), fp))
+	      if (fgets (buf, sizeof (buf), fp.get ()))
 		{
 		  char *key, *value;
 		  int i = 0;
@@ -732,12 +725,10 @@  linux_xfer_osdata_cpus (gdb_byte *readbuf,
 				     value);
 		}
 	    }
-	  while (!feof (fp));
+	  while (!feof (fp.get ()));
 
 	  if (first_item == 0)
 	    buffer_grow_str (&buffer, "</item>");
-
-	  fclose (fp);
 	}
 
       buffer_grow_str0 (&buffer, "</osdata>\n");
@@ -942,7 +933,6 @@  static void
 print_sockets (unsigned short family, int tcp, struct buffer *buffer)
 {
   const char *proc_file;
-  FILE *fp;
 
   if (family == AF_INET)
     proc_file = tcp ? "/proc/net/tcp" : "/proc/net/udp";
@@ -951,14 +941,14 @@  print_sockets (unsigned short family, int tcp, struct buffer *buffer)
   else
     return;
 
-  fp = gdb_fopen_cloexec (proc_file, "r");
+  gdb_file_up fp = gdb_fopen_cloexec (proc_file, "r");
   if (fp)
     {
       char buf[8192];
 
       do
 	{
-	  if (fgets (buf, sizeof (buf), fp))
+	  if (fgets (buf, sizeof (buf), fp.get ()))
 	    {
 	      uid_t uid;
 	      unsigned int local_port, remote_port, state;
@@ -1064,9 +1054,7 @@  print_sockets (unsigned short family, int tcp, struct buffer *buffer)
 		}
 	    }
 	}
-      while (!feof (fp));
-
-      fclose (fp);
+      while (!feof (fp.get ()));
     }
 }
 
@@ -1163,8 +1151,6 @@  linux_xfer_osdata_shm (gdb_byte *readbuf,
 
   if (offset == 0)
     {
-      FILE *fp;
-
       if (len_avail != -1 && len_avail != 0)
 	buffer_free (&buffer);
       len_avail = 0;
@@ -1172,14 +1158,14 @@  linux_xfer_osdata_shm (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"shared memory\">\n");
 
-      fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
+      gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/shm", "r");
       if (fp)
 	{
 	  char buf[8192];
 
 	  do
 	    {
-	      if (fgets (buf, sizeof (buf), fp))
+	      if (fgets (buf, sizeof (buf), fp.get ()))
 		{
 		  key_t key;
 		  uid_t uid, cuid;
@@ -1252,9 +1238,7 @@  linux_xfer_osdata_shm (gdb_byte *readbuf,
 		    }
 		}
 	    }
-	  while (!feof (fp));
-
-	  fclose (fp);
+	  while (!feof (fp.get ()));
 	}
       
       buffer_grow_str0 (&buffer, "</osdata>\n");
@@ -1291,8 +1275,6 @@  linux_xfer_osdata_sem (gdb_byte *readbuf,
 
   if (offset == 0)
     {
-      FILE *fp;
-      
       if (len_avail != -1 && len_avail != 0)
 	buffer_free (&buffer);
       len_avail = 0;
@@ -1300,14 +1282,14 @@  linux_xfer_osdata_sem (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"semaphores\">\n");
 
-      fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
+      gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/sem", "r");
       if (fp)
 	{
 	  char buf[8192];
 	  
 	  do
 	    {
-	      if (fgets (buf, sizeof (buf), fp))
+	      if (fgets (buf, sizeof (buf), fp.get ()))
 		{
 		  key_t key;
 		  uid_t uid, cuid;
@@ -1364,9 +1346,7 @@  linux_xfer_osdata_sem (gdb_byte *readbuf,
 		    }
 		}
 	    }
-	  while (!feof (fp));
-
-	  fclose (fp);
+	  while (!feof (fp.get ()));
 	}
 
       buffer_grow_str0 (&buffer, "</osdata>\n");
@@ -1403,8 +1383,6 @@  linux_xfer_osdata_msg (gdb_byte *readbuf,
 
   if (offset == 0)
     {
-      FILE *fp;
-      
       if (len_avail != -1 && len_avail != 0)
 	buffer_free (&buffer);
       len_avail = 0;
@@ -1412,14 +1390,14 @@  linux_xfer_osdata_msg (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"message queues\">\n");
       
-      fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
+      gdb_file_up fp = gdb_fopen_cloexec ("/proc/sysvipc/msg", "r");
       if (fp)
 	{
 	  char buf[8192];
 	  
 	  do
 	    {
-	      if (fgets (buf, sizeof (buf), fp))
+	      if (fgets (buf, sizeof (buf), fp.get ()))
 		{
 		  key_t key;
 		  PID_T lspid, lrpid;
@@ -1490,9 +1468,7 @@  linux_xfer_osdata_msg (gdb_byte *readbuf,
 		    }
 		}
 	    }
-	  while (!feof (fp));
-
-	  fclose (fp);
+	  while (!feof (fp.get ()));
 	}
 
       buffer_grow_str0 (&buffer, "</osdata>\n");
@@ -1529,8 +1505,6 @@  linux_xfer_osdata_modules (gdb_byte *readbuf,
 
   if (offset == 0)
     {
-      FILE *fp;
-
       if (len_avail != -1 && len_avail != 0)
 	buffer_free (&buffer);
       len_avail = 0;
@@ -1538,14 +1512,14 @@  linux_xfer_osdata_modules (gdb_byte *readbuf,
       buffer_init (&buffer);
       buffer_grow_str (&buffer, "<osdata type=\"modules\">\n");
 
-      fp = gdb_fopen_cloexec ("/proc/modules", "r");
+      gdb_file_up fp = gdb_fopen_cloexec ("/proc/modules", "r");
       if (fp)
 	{
 	  char buf[8192];
 	  
 	  do
 	    {
-	      if (fgets (buf, sizeof (buf), fp))
+	      if (fgets (buf, sizeof (buf), fp.get ()))
 		{
 		  char *name, *dependencies, *status, *tmp;
 		  unsigned int size;
@@ -1600,9 +1574,7 @@  linux_xfer_osdata_modules (gdb_byte *readbuf,
 			address);
 		}
 	    }
-	  while (!feof (fp));
-
-	  fclose (fp);
+	  while (!feof (fp.get ()));
 	}
 
       buffer_grow_str0 (&buffer, "</osdata>\n");
diff --git a/gdb/nat/linux-procfs.c b/gdb/nat/linux-procfs.c
index 5290045..a12f622 100644
--- a/gdb/nat/linux-procfs.c
+++ b/gdb/nat/linux-procfs.c
@@ -29,12 +29,11 @@  static int
 linux_proc_get_int (pid_t lwpid, const char *field, int warn)
 {
   size_t field_len = strlen (field);
-  FILE *status_file;
   char buf[100];
   int retval = -1;
 
   snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid);
-  status_file = gdb_fopen_cloexec (buf, "r");
+  gdb_file_up status_file = gdb_fopen_cloexec (buf, "r");
   if (status_file == NULL)
     {
       if (warn)
@@ -42,14 +41,13 @@  linux_proc_get_int (pid_t lwpid, const char *field, int warn)
       return -1;
     }
 
-  while (fgets (buf, sizeof (buf), status_file))
+  while (fgets (buf, sizeof (buf), status_file.get ()))
     if (strncmp (buf, field, field_len) == 0 && buf[field_len] == ':')
       {
 	retval = strtol (&buf[field_len + 1], NULL, 10);
 	break;
       }
 
-  fclose (status_file);
   return retval;
 }
 
@@ -128,12 +126,11 @@  parse_proc_status_state (const char *state)
 static int
 linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
 {
-  FILE *procfile;
   int have_state;
   char buffer[100];
 
   xsnprintf (buffer, sizeof (buffer), "/proc/%d/status", (int) pid);
-  procfile = gdb_fopen_cloexec (buffer, "r");
+  gdb_file_up procfile = gdb_fopen_cloexec (buffer, "r");
   if (procfile == NULL)
     {
       if (warn)
@@ -142,14 +139,13 @@  linux_proc_pid_get_state (pid_t pid, int warn, enum proc_state *state)
     }
 
   have_state = 0;
-  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
+  while (fgets (buffer, sizeof (buffer), procfile.get ()) != NULL)
     if (startswith (buffer, "State:"))
       {
 	have_state = 1;
 	*state = parse_proc_status_state (buffer + sizeof ("State:") - 1);
 	break;
       }
-  fclose (procfile);
   return have_state;
 }
 
@@ -242,7 +238,6 @@  linux_proc_tid_get_name (ptid_t ptid)
 
   static char comm_buf[TASK_COMM_LEN];
   char comm_path[100];
-  FILE *comm_file;
   const char *comm_val;
   pid_t pid = ptid_get_pid (ptid);
   pid_t tid = ptid_lwp_p (ptid) ? ptid_get_lwp (ptid) : ptid_get_pid (ptid);
@@ -250,12 +245,11 @@  linux_proc_tid_get_name (ptid_t ptid)
   xsnprintf (comm_path, sizeof (comm_path),
 	     "/proc/%ld/task/%ld/comm", (long) pid, (long) tid);
 
-  comm_file = gdb_fopen_cloexec (comm_path, "r");
+  gdb_file_up comm_file = gdb_fopen_cloexec (comm_path, "r");
   if (comm_file == NULL)
     return NULL;
 
-  comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file);
-  fclose (comm_file);
+  comm_val = fgets (comm_buf, sizeof (comm_buf), comm_file.get ());
 
   if (comm_val != NULL)
     {
diff --git a/gdb/remote.c b/gdb/remote.c
index d363a36..c381743 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -11902,7 +11902,6 @@  remote_file_put (const char *local_file, const char *remote_file, int from_tty)
 {
   struct cleanup *back_to, *close_cleanup;
   int retcode, fd, remote_errno, bytes, io_size;
-  FILE *file;
   gdb_byte *buffer;
   int bytes_in_buffer;
   int saw_eof;
@@ -11912,10 +11911,9 @@  remote_file_put (const char *local_file, const char *remote_file, int from_tty)
   if (!rs->remote_desc)
     error (_("command can only be used with remote target"));
 
-  file = gdb_fopen_cloexec (local_file, "rb");
+  gdb_file_up file = gdb_fopen_cloexec (local_file, "rb");
   if (file == NULL)
     perror_with_name (local_file);
-  back_to = make_cleanup_fclose (file);
 
   fd = remote_hostio_open (find_target_at (process_stratum), NULL,
 			   remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
@@ -11928,7 +11926,7 @@  remote_file_put (const char *local_file, const char *remote_file, int from_tty)
      remote packet limit, so we'll transfer slightly fewer.  */
   io_size = get_remote_packet_size ();
   buffer = (gdb_byte *) xmalloc (io_size);
-  make_cleanup (xfree, buffer);
+  back_to = make_cleanup (xfree, buffer);
 
   close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
 
@@ -11941,10 +11939,10 @@  remote_file_put (const char *local_file, const char *remote_file, int from_tty)
 	{
 	  bytes = fread (buffer + bytes_in_buffer, 1,
 			 io_size - bytes_in_buffer,
-			 file);
+			 file.get ());
 	  if (bytes == 0)
 	    {
-	      if (ferror (file))
+	      if (ferror (file.get ()))
 		error (_("Error reading %s."), local_file);
 	      else
 		{
@@ -11995,7 +11993,6 @@  remote_file_get (const char *remote_file, const char *local_file, int from_tty)
 {
   struct cleanup *back_to, *close_cleanup;
   int fd, remote_errno, bytes, io_size;
-  FILE *file;
   gdb_byte *buffer;
   ULONGEST offset;
   struct remote_state *rs = get_remote_state ();
@@ -12009,16 +12006,15 @@  remote_file_get (const char *remote_file, const char *local_file, int from_tty)
   if (fd == -1)
     remote_hostio_error (remote_errno);
 
-  file = gdb_fopen_cloexec (local_file, "wb");
+  gdb_file_up file = gdb_fopen_cloexec (local_file, "wb");
   if (file == NULL)
     perror_with_name (local_file);
-  back_to = make_cleanup_fclose (file);
 
   /* Send up to this many bytes at once.  They won't all fit in the
      remote packet limit, so we'll transfer slightly fewer.  */
   io_size = get_remote_packet_size ();
   buffer = (gdb_byte *) xmalloc (io_size);
-  make_cleanup (xfree, buffer);
+  back_to = make_cleanup (xfree, buffer);
 
   close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
 
@@ -12035,7 +12031,7 @@  remote_file_get (const char *remote_file, const char *local_file, int from_tty)
 
       offset += bytes;
 
-      bytes = fwrite (buffer, 1, bytes, file);
+      bytes = fwrite (buffer, 1, bytes, file.get ());
       if (bytes == 0)
 	perror_with_name (local_file);
     }
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index d479cef..fb4283f 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -89,7 +89,7 @@  tfile_start (struct trace_file_writer *self, const char *filename)
     = (struct tfile_trace_file_writer *) self;
 
   writer->pathname = tilde_expand (filename);
-  writer->fp = gdb_fopen_cloexec (writer->pathname, "wb");
+  writer->fp = gdb_fopen_cloexec (writer->pathname, "wb").release ();
   if (writer->fp == NULL)
     error (_("Unable to open file '%s' for saving trace data (%s)"),
 	   writer->pathname, safe_strerror (errno));
diff --git a/gdb/ui-file.c b/gdb/ui-file.c
index 60e3274..046e14f 100644
--- a/gdb/ui-file.c
+++ b/gdb/ui-file.c
@@ -177,12 +177,12 @@  stdio_file::open (const char *name, const char *mode)
       m_close_p = false;
     }
 
-  FILE *f = gdb_fopen_cloexec (name, mode);
+  gdb_file_up f = gdb_fopen_cloexec (name, mode);
 
   if (f == NULL)
     return false;
 
-  set_stream (f);
+  set_stream (f.release ());
   m_close_p = true;
 
   return true;
diff --git a/gdb/xml-support.c b/gdb/xml-support.c
index fff3997..65638b9 100644
--- a/gdb/xml-support.c
+++ b/gdb/xml-support.c
@@ -1001,7 +1001,7 @@  char *
 xml_fetch_content_from_file (const char *filename, void *baton)
 {
   const char *dirname = (const char *) baton;
-  FILE *file;
+  gdb_file_up file;
   struct cleanup *back_to;
   char *text;
   size_t len, offset;
@@ -1021,21 +1021,19 @@  xml_fetch_content_from_file (const char *filename, void *baton)
   if (file == NULL)
     return NULL;
 
-  back_to = make_cleanup_fclose (file);
-
   /* Read in the whole file, one chunk at a time.  */
   len = 4096;
   offset = 0;
   text = (char *) xmalloc (len);
-  make_cleanup (free_current_contents, &text);
+  back_to = make_cleanup (free_current_contents, &text);
   while (1)
     {
       size_t bytes_read;
 
       /* Continue reading where the last read left off.  Leave at least
 	 one byte so that we can NUL-terminate the result.  */
-      bytes_read = fread (text + offset, 1, len - offset - 1, file);
-      if (ferror (file))
+      bytes_read = fread (text + offset, 1, len - offset - 1, file.get ());
+      if (ferror (file.get ()))
 	{
 	  warning (_("Read error from \"%s\""), filename);
 	  do_cleanups (back_to);
@@ -1044,14 +1042,13 @@  xml_fetch_content_from_file (const char *filename, void *baton)
 
       offset += bytes_read;
 
-      if (feof (file))
+      if (feof (file.get ()))
 	break;
 
       len = len * 2;
       text = (char *) xrealloc (text, len);
     }
 
-  fclose (file);
   discard_cleanups (back_to);
 
   text[offset] = '\0';