winpr-comm, winpr-file: better initialization of the static variables
authorEmmanuel Ledoux <eledoux@hp.com>
Thu, 19 Jun 2014 10:03:36 +0000 (12:03 +0200)
committerEmmanuel Ledoux <emmanuel.ledoux@hp.com>
Thu, 19 Jun 2014 10:03:36 +0000 (12:03 +0200)
winpr/include/winpr/file.h
winpr/libwinpr/comm/comm.c
winpr/libwinpr/file/file.c

index 9f8d748..ef5c4dd 100644 (file)
@@ -321,7 +321,7 @@ typedef HANDLE (*pcCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD
 typedef struct _HANDLE_CREATOR
 {
        pcIsHandled IsHandled;
-       pcCreateFileA CreateFileA; /* TMP: FIXME: CreateFileA or CreateFile ? */
+       pcCreateFileA CreateFileA;
 } HANDLE_CREATOR, *PHANDLE_CREATOR, *LPHANDLE_CREATOR;
 
 BOOL RegisterHandleCreator(PHANDLE_CREATOR pHandleCreator);
index 39bde3b..b99d532 100644 (file)
 
 #ifndef _WIN32
 
+#include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <termios.h>
 #include <unistd.h>
 
-#include <errno.h>
-
 #include <freerdp/utils/debug.h>
 
 #include <winpr/crt.h>
@@ -749,31 +750,33 @@ typedef struct _COMM_DEVICE
 } COMM_DEVICE;
 
 /* FIXME: get a clever data structure, see also io.h functions */
-static COMM_DEVICE **_CommDevices = NULL;
-
+/* _CommDevices is a NULL-terminated array with a maximun of COMM_DEVICE_MAX COMM_DEVICE */
 #define COMM_DEVICE_MAX        128
+static COMM_DEVICE **_CommDevices = NULL;
 
 static HANDLE_CREATOR *_CommHandleCreator = NULL;
 
-
-static void _CommDevicesInit()
+static pthread_once_t _CommInitialized = PTHREAD_ONCE_INIT;
+static void _CommInit()
 {
-       /*
-        * TMP: FIXME: What kind of mutex should be used here?
-        * better have to let DefineCommDevice() and QueryCommDevice() thread unsafe ?
-        * use of a module_init() ?
-        */
+       /* NB: error management to be done outside of this function */
 
-       if (_CommDevices == NULL)
-       {
-               _CommDevices = (COMM_DEVICE**)calloc(COMM_DEVICE_MAX+1, sizeof(COMM_DEVICE*));
+       assert(_CommDevices == NULL);
+       assert(_CommHandleCreator == NULL);
+
+       _CommDevices = (COMM_DEVICE**)calloc(COMM_DEVICE_MAX+1, sizeof(COMM_DEVICE*));
 
-               _CommHandleCreator = (HANDLE_CREATOR*)malloc(sizeof(HANDLE_CREATOR));
+       _CommHandleCreator = (HANDLE_CREATOR*)malloc(sizeof(HANDLE_CREATOR));
+       if (_CommHandleCreator)
+       {
                _CommHandleCreator->IsHandled = IsCommDevice;
                _CommHandleCreator->CreateFileA = CommCreateFileA;
-
+               
                RegisterHandleCreator(_CommHandleCreator);
        }
+
+       assert(_CommDevices != NULL);
+       assert(_CommHandleCreator != NULL);
 }
 
 
@@ -818,6 +821,7 @@ static BOOL _IsReservedCommDeviceName(LPCTSTR lpName)
  * information, call GetLastError.
  *
  * ERRORS:
+ *   ERROR_DLL_INIT_FAILED
  *   ERROR_OUTOFMEMORY was not possible to get mappings.
  *   ERROR_INVALID_DATA was not possible to add the device.
  */
@@ -827,10 +831,15 @@ BOOL DefineCommDevice(/* DWORD dwFlags,*/ LPCTSTR lpDeviceName, LPCTSTR lpTarget
        LPTSTR storedDeviceName = NULL;
        LPTSTR storedTargetPath = NULL;
 
-       _CommDevicesInit();
+       if (pthread_once(&_CommInitialized, _CommInit) != 0)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
+               goto error_handle;
+       }
+
        if (_CommDevices == NULL)
        {
-               SetLastError(ERROR_OUTOFMEMORY);
+               SetLastError(ERROR_DLL_INIT_FAILED);
                goto error_handle;
        }
 
@@ -918,6 +927,7 @@ BOOL DefineCommDevice(/* DWORD dwFlags,*/ LPCTSTR lpDeviceName, LPCTSTR lpTarget
  *
  * ERRORS:
  *   ERROR_SUCCESS
+ *   ERROR_DLL_INIT_FAILED
  *   ERROR_OUTOFMEMORY was not possible to get mappings.
  *   ERROR_NOT_SUPPORTED equivalent QueryDosDevice feature not supported.
  *   ERROR_INVALID_DATA was not possible to retrieve any device information.
@@ -930,10 +940,15 @@ DWORD QueryCommDevice(LPCTSTR lpDeviceName, LPTSTR lpTargetPath, DWORD ucchMax)
 
        SetLastError(ERROR_SUCCESS);
 
-       _CommDevicesInit();
+       if (pthread_once(&_CommInitialized, _CommInit) != 0)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
+               return 0;
+       }
+
        if (_CommDevices == NULL)
        {
-               SetLastError(ERROR_OUTOFMEMORY);
+               SetLastError(ERROR_DLL_INIT_FAILED);
                return 0;
        }
 
index 4908a71..a48e1be 100644 (file)
@@ -42,7 +42,7 @@
 
 /**
  * api-ms-win-core-file-l1-2-0.dll:
- * 
+ *
  * CreateFileA
  * CreateFileW
  * CreateFile2
 #include <unistd.h>
 #endif
 
+#include <assert.h>
 #include <time.h>
 #include <errno.h>
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
  * winpr-collections to avoid a circular dependency
  * _HandleCreators = ArrayList_New(TRUE);
  */
-static HANDLE_CREATOR **_HandleCreators = NULL;
-
+/* _HandleCreators is a NULL-terminated array with a maximun of HANDLE_CREATOR_MAX HANDLE_CREATOR */
 #define HANDLE_CREATOR_MAX 128
+static HANDLE_CREATOR **_HandleCreators = NULL;
 
+static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
 static void _HandleCreatorsInit()
 {
-       /* 
-        * TMP: FIXME: What kind of mutex should be used here? use of
-        * a module_init()?
-        */ 
+       /* NB: error management to be done outside of this function */
 
-       if (_HandleCreators == NULL)
-       {
-               _HandleCreators = (HANDLE_CREATOR**)calloc(HANDLE_CREATOR_MAX+1, sizeof(HANDLE_CREATOR*));
-       }
+       assert(_HandleCreators == NULL);
+
+       _HandleCreators = (HANDLE_CREATOR**)calloc(HANDLE_CREATOR_MAX+1, sizeof(HANDLE_CREATOR*));
+
+       assert(_HandleCreators != NULL);
 }
 
 /**
  * Returns TRUE on success, FALSE otherwise.
  *
  * ERRORS:
+ *   ERROR_DLL_INIT_FAILED
  *   ERROR_INSUFFICIENT_BUFFER _HandleCreators full
  */
 BOOL RegisterHandleCreator(PHANDLE_CREATOR pHandleCreator)
 {
        int i;
 
-       _HandleCreatorsInit();
+       if (pthread_once(&_HandleCreatorsInitialized, _HandleCreatorsInit) != 0)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
+               return FALSE;
+       }
+
+       if (_HandleCreators == NULL)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
+               return FALSE;
+       }
+
 
        for (i=0; i<HANDLE_CREATOR_MAX; i++)
        {
@@ -265,7 +278,7 @@ int InstallAioSignalHandler()
 #endif /* HAVE_AIO_H */
 
 HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
-                  DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+               DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
 {
        int i;
        char* name;
@@ -277,9 +290,17 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
        if (!lpFileName)
                return INVALID_HANDLE_VALUE;
 
-       _HandleCreatorsInit();
+       if (pthread_once(&_HandleCreatorsInitialized, _HandleCreatorsInit) != 0)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
+               return INVALID_HANDLE_VALUE;
+       }
+
        if (_HandleCreators == NULL)
+       {
+               SetLastError(ERROR_DLL_INIT_FAILED);
                return INVALID_HANDLE_VALUE;
+       }
 
        for (i=0; _HandleCreators[i] != NULL; i++)
        {
@@ -291,7 +312,7 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
                }
        }
 
-       /* * */
+       /* TODO: use of a HANDLE_CREATOR for named pipes as well */
 
        if (!IsNamedPipeFileNameA(lpFileName))
                return INVALID_HANDLE_VALUE;