提交 f04de501 编写于 作者: S Stefan Berger

Introduce VIR_CLOSE to be used rather than close()

Since bugs due to double-closed file descriptors are difficult to track down in a multi-threaded system, I am introducing the VIR_CLOSE(fd) macro to help avoid mistakes here.

There are lots of places where close() is being used. In this patch I am only cleaning up usage of close() in src/conf where the problems were.

I also dare to declare close() as being deprecated in libvirt code base (HACKING).
上级 b2c9a879
...@@ -318,6 +318,23 @@ routines, use the macros from memory.h ...@@ -318,6 +318,23 @@ routines, use the macros from memory.h
VIR_FREE(domain); VIR_FREE(domain);
File handling
=============
Use of the close() API is deprecated in libvirt code base to help avoiding
double-closing of a file descriptor. Instead of this API, use the macro from
files.h
- eg close a file descriptor
if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, _("failed to close file"));
}
- eg close a file descriptor in an error path, without losing the previous
errno value
VIR_FORCE_CLOSE(fd);
String comparisons String comparisons
================== ==================
......
...@@ -389,7 +389,30 @@ ...@@ -389,7 +389,30 @@
</pre></li> </pre></li>
</ul> </ul>
<h2><a name="file_handling">File handling</a></h2>
<p>
Use of the close() API is deprecated in libvirt code base to help
avoiding double-closing of a file descriptor. Instead of this API,
use the macro from files.h
</p>
<ul>
<li><p>eg close a file descriptor</p>
<pre>
if (VIR_CLOSE(fd) &lt; 0) {
virReportSystemError(errno, _("failed to close file"));
}
</pre></li>
<li><p>eg close a file descriptor in an error path, without losing
the previous errno value</p>
<pre>
VIR_FORCE_CLOSE(fd);
</pre></li>
</ul>
<h2><a name="string_comparision">String comparisons</a></h2> <h2><a name="string_comparision">String comparisons</a></h2>
......
...@@ -82,7 +82,8 @@ UTIL_SOURCES = \ ...@@ -82,7 +82,8 @@ UTIL_SOURCES = \
util/uuid.c util/uuid.h \ util/uuid.c util/uuid.h \
util/util.c util/util.h \ util/util.c util/util.h \
util/xml.c util/xml.h \ util/xml.c util/xml.h \
util/virterror.c util/virterror_internal.h util/virterror.c util/virterror_internal.h \
util/files.c util/files.h
EXTRA_DIST += util/threads-pthread.c util/threads-win32.c EXTRA_DIST += util/threads-pthread.c util/threads-win32.c
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "nwfilter_conf.h" #include "nwfilter_conf.h"
#include "ignore-value.h" #include "ignore-value.h"
#include "storage_file.h" #include "storage_file.h"
#include "files.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN #define VIR_FROM_THIS VIR_FROM_DOMAIN
...@@ -6798,7 +6799,7 @@ int virDomainSaveXML(const char *configDir, ...@@ -6798,7 +6799,7 @@ int virDomainSaveXML(const char *configDir,
goto cleanup; goto cleanup;
} }
if (close(fd) < 0) { if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot save config file '%s'"), _("cannot save config file '%s'"),
configFile); configFile);
...@@ -6807,8 +6808,8 @@ int virDomainSaveXML(const char *configDir, ...@@ -6807,8 +6808,8 @@ int virDomainSaveXML(const char *configDir,
ret = 0; ret = 0;
cleanup: cleanup:
if (fd != -1) VIR_FORCE_CLOSE(fd);
close(fd);
VIR_FREE(configFile); VIR_FREE(configFile);
return ret; return ret;
} }
...@@ -7765,10 +7766,14 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk, ...@@ -7765,10 +7766,14 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
} }
if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) { if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
close(fd); VIR_FORCE_CLOSE(fd);
goto cleanup; goto cleanup;
} }
close(fd);
if (VIR_CLOSE(fd) < 0)
virReportSystemError(errno,
_("could not close file %s"),
path);
if (virHashAddEntry(paths, path, (void*)0x1) < 0) { if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
virReportOOMError(); virReportOOMError();
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "util.h" #include "util.h"
#include "buf.h" #include "buf.h"
#include "c-ctype.h" #include "c-ctype.h"
#include "files.h"
#define MAX_BRIDGE_ID 256 #define MAX_BRIDGE_ID 256
#define VIR_FROM_THIS VIR_FROM_NETWORK #define VIR_FROM_THIS VIR_FROM_NETWORK
...@@ -687,7 +688,7 @@ int virNetworkSaveXML(const char *configDir, ...@@ -687,7 +688,7 @@ int virNetworkSaveXML(const char *configDir,
goto cleanup; goto cleanup;
} }
if (close(fd) < 0) { if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot save config file '%s'"), _("cannot save config file '%s'"),
configFile); configFile);
...@@ -697,8 +698,7 @@ int virNetworkSaveXML(const char *configDir, ...@@ -697,8 +698,7 @@ int virNetworkSaveXML(const char *configDir,
ret = 0; ret = 0;
cleanup: cleanup:
if (fd != -1) VIR_FORCE_CLOSE(fd);
close(fd);
VIR_FREE(configFile); VIR_FREE(configFile);
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "nwfilter_conf.h" #include "nwfilter_conf.h"
#include "domain_conf.h" #include "domain_conf.h"
#include "c-ctype.h" #include "c-ctype.h"
#include "files.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER #define VIR_FROM_THIS VIR_FROM_NWFILTER
...@@ -2193,7 +2194,7 @@ int virNWFilterSaveXML(const char *configDir, ...@@ -2193,7 +2194,7 @@ int virNWFilterSaveXML(const char *configDir,
goto cleanup; goto cleanup;
} }
if (close(fd) < 0) { if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot save config file '%s'"), _("cannot save config file '%s'"),
configFile); configFile);
...@@ -2203,9 +2204,7 @@ int virNWFilterSaveXML(const char *configDir, ...@@ -2203,9 +2204,7 @@ int virNWFilterSaveXML(const char *configDir,
ret = 0; ret = 0;
cleanup: cleanup:
if (fd != -1) VIR_FORCE_CLOSE(fd);
close(fd);
VIR_FREE(configFile); VIR_FREE(configFile);
return ret; return ret;
...@@ -2604,7 +2603,7 @@ virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver, ...@@ -2604,7 +2603,7 @@ virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver,
goto cleanup; goto cleanup;
} }
if (close(fd) < 0) { if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot save config file %s"), _("cannot save config file %s"),
pool->configFile); pool->configFile);
...@@ -2614,8 +2613,7 @@ virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver, ...@@ -2614,8 +2613,7 @@ virNWFilterPoolObjSaveDef(virNWFilterDriverStatePtr driver,
ret = 0; ret = 0;
cleanup: cleanup:
if (fd != -1) VIR_FORCE_CLOSE(fd);
close(fd);
VIR_FREE(xml); VIR_FREE(xml);
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "buf.h" #include "buf.h"
#include "util.h" #include "util.h"
#include "memory.h" #include "memory.h"
#include "files.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE #define VIR_FROM_THIS VIR_FROM_STORAGE
...@@ -1560,7 +1561,7 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, ...@@ -1560,7 +1561,7 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
goto cleanup; goto cleanup;
} }
if (close(fd) < 0) { if (VIR_CLOSE(fd) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot save config file %s"), _("cannot save config file %s"),
pool->configFile); pool->configFile);
...@@ -1570,9 +1571,7 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, ...@@ -1570,9 +1571,7 @@ virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
ret = 0; ret = 0;
cleanup: cleanup:
if (fd != -1) VIR_FORCE_CLOSE(fd);
close(fd);
VIR_FREE(xml); VIR_FREE(xml);
return ret; return ret;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "xml.h" #include "xml.h"
#include "virterror_internal.h" #include "virterror_internal.h"
#include "uuid.h" #include "uuid.h"
#include "files.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE #define VIR_FROM_THIS VIR_FROM_STORAGE
...@@ -286,12 +287,12 @@ virStorageGenerateQcowPassphrase(unsigned char *dest) ...@@ -286,12 +287,12 @@ virStorageGenerateQcowPassphrase(unsigned char *dest)
if (r <= 0) { if (r <= 0) {
virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s", virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot read from /dev/urandom")); _("Cannot read from /dev/urandom"));
close(fd); VIR_FORCE_CLOSE(fd);
return -1; return -1;
} }
if (dest[i] >= 0x20 && dest[i] <= 0x7E) if (dest[i] >= 0x20 && dest[i] <= 0x7E)
i++; /* Got an acceptable character */ i++; /* Got an acceptable character */
} }
close(fd); VIR_FORCE_CLOSE(fd);
return 0; return 0;
} }
...@@ -769,3 +769,6 @@ virXPathLongLong; ...@@ -769,3 +769,6 @@ virXPathLongLong;
virXPathULongLong; virXPathULongLong;
virXPathLongHex; virXPathLongHex;
virXPathULongHex; virXPathULongHex;
# files.h
virClose;
/*
* memory.c: safer file handling
*
* Copyright (C) 2010 IBM Corporation
* Copyright (C) 2010 Stefan Berger
* Copyright (C) 2010 RedHat, Inc.
* Copyright (C) 2010 Eric Blake
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <config.h>
#include <unistd.h>
#include "files.h"
int virClose(int *fdptr, bool preserve_errno)
{
int saved_errno;
int rc = 0;
if (*fdptr >= 0) {
if (preserve_errno)
saved_errno = errno;
rc = close(*fdptr);
*fdptr = -1;
if (preserve_errno)
errno = saved_errno;
}
return rc;
}
/*
* files.h: safer file handling
*
* Copyright (C) 2010 IBM Corporation
* Copyright (C) 2010 Stefan Berger
* Copyright (C) 2010 RedHat, Inc.
* Copyright (C) 2010 Eric Blake
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __VIR_FILES_H_
# define __VIR_FILES_H_
# include <stdbool.h>
# include "internal.h"
# include "ignore-value.h"
/* Don't call this directly - use the macros below */
int virClose(int *fdptr, bool preserve_errno) ATTRIBUTE_RETURN_CHECK;
/* For use on normal paths; caller must check return value,
and failure sets errno per close(). */
# define VIR_CLOSE(FD) virClose(&(FD), false)
/* For use on cleanup paths; errno is unaffected by close,
and no return value to worry about. */
# define VIR_FORCE_CLOSE(FD) ignore_value(virClose(&(FD), true))
#endif /* __VIR_FILES_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册