Hi,
In CRT versions greater than Server 2003, the close() function checks
its parameters.
It expects a valid file descriptor ( the param check definition seems to
say that an int is expected which should be a valid file descriptor.)
So, the int / file descriptor we pass to close() is being interpreted as
invalid.
On older crts, there is no param check - so close proceeds and returns
-1 if it fails.
But on new CRTs, the param is checked first, and if invalid, the
standard invalid parameter handler is called. This default handler exits
the application. It seems utter nonesense that by default close() can
never return -1. But that's how it seems to be.
see http://msdn.microsoft.com/en-us/library/5fzwd5ss.aspx
You can also look at the Server 2003 version from that page which
indicates close() simply returns -1 if it does not succeed.
My current workaround is in the attached patch which makes build.c
rather ugly. I do nothing in my custom invalid parameter handler leaving
close() to behave as in earlier CRTs.
Why the descriptor is found invalid I don't know. It is always '3' ( so
not -1 ) which seems reasonable as at that stage in the code everything
is constant.
I tried changing the open flags to different params with no joy.
On 22/07/2011 07:34, Roderich Schupp wrote:
On Thu, Jul 21, 2011 at 9:04 PM, Mark Dootson<mark.doot...@znix.com> wrote:
The close(fh) statements in boot.c may cause application to crash if the CRT
version is 1400 or above for 32 bit or 1500 and above for 64 bit.
What exactly is the problem with close(fh) here? Invalid fh?
Cheers, Roderich
Index: myldr/boot.c
===================================================================
--- myldr/boot.c (revision 1271)
+++ myldr/boot.c (working copy)
@@ -1,6 +1,12 @@
#undef readdir
-
+#ifdef _MSC_VER
+#include <io.h>
+#if ( _MSC_VER > 1400 ) || ( _MSC_VER >= 1400 && !defined(_WIN64) )
+#define PAR_MS_CRT_MODERN
+#endif
+#else
#include <unistd.h>
+#endif
typedef struct my_chunk
{
@@ -25,6 +31,29 @@
#include "my_libgcc.c"
#endif
+#ifdef PAR_MS_CRT_MODERN
+void myInvalidCloseParameterHandler(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
+ unsigned int line,
+ uintptr_t pReserved)
+{ }
+#endif
+
+int my_close_fh (int fh) {
+ int rval;
+#ifdef PAR_MS_CRT_MODERN
+ _invalid_parameter_handler oldHandler, newHandler;
+ newHandler = myInvalidCloseParameterHandler;
+ oldHandler = _set_invalid_parameter_handler(newHandler);
+#endif
+ rval = close(fh);
+#ifdef PAR_MS_CRT_MODERN
+ _set_invalid_parameter_handler(oldHandler);
+#endif
+ return rval;
+}
+
int my_mkfile (char* argv0, char* stmpdir, const char* name, off_t
expected_size, char** file_p) {
int i;
struct stat statbuf;
@@ -67,7 +96,7 @@
#define ASFW_ANY -1
#endif
#endif
-
+
par_init_env();
stmpdir = par_mktmpdir( argv );
@@ -76,7 +105,7 @@
fprintf(stderr, "%s: creation of private temporary subdirectory %s
failed - aborting with errno %i.\n", argv[0], stmpdir, errno);
return 2;
}
-
+
/* extract custom Perl interpreter into stmpdir
(but under the same basename as argv[0]) */
i = my_mkfile( argv[0],
@@ -84,9 +113,9 @@
size_load_my_par, &my_perl );
if ( !i ) return 2;
if ( i != -2 ) {
- if (write_chunks(chunks_load_my_par, i) || close(i))
+ if (write_chunks(chunks_load_my_par, i) || my_close_fh(i))
return 2;
- close(i);
+ my_close_fh(i);
chmod(my_perl, 0755);
#ifdef __hpux
{
@@ -102,7 +131,7 @@
i = my_mkfile( argv[0], stmpdir, name_load_my_libperl,
size_load_my_libperl, &my_file );
if ( !i ) return 2;
if ( i != -2 ) {
- if (write_chunks(chunks_load_my_libperl, i) || close(i))
+ if (write_chunks(chunks_load_my_libperl, i) || my_close_fh(i))
return 2;
chmod(my_file, 0755);
}
@@ -112,7 +141,7 @@
i = my_mkfile( argv[0], stmpdir, name_load_my_libgcc, size_load_my_libgcc,
&my_file );
if ( !i ) return 2;
if ( i != -2 ) {
- if (write_chunks(chunks_load_my_libgcc, i) || close(i))
+ if (write_chunks(chunks_load_my_libgcc, i) || my_close_fh(i))
return 2;
chmod(my_file, 0755);
}