Fixed close for socket to properly release the socket context structure and the handle.

Signed-off-by: lpleahy


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13802 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lpleahy 2012-10-08 21:39:35 +00:00
parent e06a4cd134
commit 4652be0c5a
7 changed files with 295 additions and 111 deletions

View File

@ -31,7 +31,6 @@ BslSocketCloseWork (
IN int * pErrno IN int * pErrno
) )
{ {
EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
EFI_STATUS Status; EFI_STATUS Status;
// //
@ -50,21 +49,9 @@ BslSocketCloseWork (
} }
if ( !EFI_ERROR ( Status )) { if ( !EFI_ERROR ( Status )) {
// //
// Locate the socket protocol // Release the socket resources
// //
Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid, *pErrno = EslServiceFreeProtocol ( pSocketProtocol );
NULL,
(VOID **) &pServiceBinding );
if ( !EFI_ERROR ( Status )) {
//
// Release the handle
//
Status = pServiceBinding->DestroyChild ( pServiceBinding,
pSocketProtocol->SocketHandle );
}
if ( EFI_ERROR ( Status )) {
*pErrno = EIO;
}
} }
else { else {
DEBUG (( DEBUG_ERROR, DEBUG (( DEBUG_ERROR,

View File

@ -91,11 +91,8 @@ EslDxeDestroyChild (
) )
{ {
ESL_LAYER * pLayer; ESL_LAYER * pLayer;
ESL_SOCKET * pSocket;
ESL_SOCKET * pSocketPrevious;
EFI_SOCKET_PROTOCOL * pSocketProtocol; EFI_SOCKET_PROTOCOL * pSocketProtocol;
EFI_STATUS Status; EFI_STATUS Status;
EFI_TPL TplPrevious;
DBG_ENTER ( ); DBG_ENTER ( );
@ -112,101 +109,10 @@ EslDxeDestroyChild (
EFI_OPEN_PROTOCOL_GET_PROTOCOL EFI_OPEN_PROTOCOL_GET_PROTOCOL
); );
if ( !EFI_ERROR ( Status )) { if ( !EFI_ERROR ( Status )) {
pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
// //
// Synchronize with the socket layer // Free the socket resources
// //
RAISE_TPL ( TplPrevious, TPL_SOCKETS ); Status = EslSocketFree ( pSocketProtocol, NULL );
//
// Walk the socket list
//
pSocketPrevious = pLayer->pSocketList;
if ( NULL != pSocketPrevious ) {
if ( pSocket == pSocketPrevious ) {
//
// Remove the socket from the head of the list
//
pLayer->pSocketList = pSocket->pNext;
}
else {
//
// Find the socket in the middle of the list
//
while (( NULL != pSocketPrevious )
&& ( pSocket != pSocketPrevious->pNext )) {
//
// Set the next socket
//
pSocketPrevious = pSocketPrevious->pNext;
}
if ( NULL != pSocketPrevious ) {
//
// Remove the socket from the middle of the list
//
pSocketPrevious = pSocket->pNext;
}
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL,
"ERROR - Socket list is empty!\r\n" ));
}
//
// Release the socket layer synchronization
//
RESTORE_TPL ( TplPrevious );
//
// Determine if the socket was found
//
if ( NULL != pSocketPrevious ) {
pSocket->pNext = NULL;
//
// Remove the socket protocol
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiSocketProtocolGuid,
&pSocket->SocketProtocol,
NULL );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL | DEBUG_INFO,
"Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
ChildHandle ));
//
// Free the socket structure
//
Status = gBS->FreePool ( pSocket );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL,
"0x%08x: Free pSocket, %d bytes\r\n",
pSocket,
sizeof ( *pSocket )));
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL,
"ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
pSocket,
Status ));
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
"ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
ChildHandle,
Status ));
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_INFO,
"ERROR - The socket was not in the socket list!\r\n" ));
Status = EFI_NOT_FOUND;
}
} }
else { else {
DEBUG (( DEBUG_ERROR, DEBUG (( DEBUG_ERROR,

View File

@ -1945,6 +1945,168 @@ EslSocketCopyFragmentedBuffer (
} }
/**
Free the socket.
This routine frees the socket structure and handle resources.
The ::close routine calls EslServiceFreeProtocol which then calls
this routine to free the socket context structure and close the
handle.
@param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
@param [out] pErrno Address to receive the errno value upon completion.
@retval EFI_SUCCESS The socket resources were returned successfully.
**/
EFI_STATUS
EslSocketFree (
IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
IN int * pErrno
)
{
EFI_HANDLE ChildHandle;
int errno;
ESL_LAYER * pLayer;
ESL_SOCKET * pSocket;
ESL_SOCKET * pSocketPrevious;
EFI_STATUS Status;
EFI_TPL TplPrevious;
DBG_ENTER ( );
//
// Assume failure
//
errno = EIO;
pSocket = NULL;
Status = EFI_INVALID_PARAMETER;
//
// Validate the socket
//
pLayer = &mEslLayer;
if ( NULL != pSocketProtocol ) {
pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
//
// Synchronize with the socket layer
//
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
//
// Walk the socket list
//
pSocketPrevious = pLayer->pSocketList;
if ( NULL != pSocketPrevious ) {
if ( pSocket == pSocketPrevious ) {
//
// Remove the socket from the head of the list
//
pLayer->pSocketList = pSocket->pNext;
}
else {
//
// Find the socket in the middle of the list
//
while (( NULL != pSocketPrevious )
&& ( pSocket != pSocketPrevious->pNext )) {
//
// Set the next socket
//
pSocketPrevious = pSocketPrevious->pNext;
}
if ( NULL != pSocketPrevious ) {
//
// Remove the socket from the middle of the list
//
pSocketPrevious = pSocket->pNext;
}
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL,
"ERROR - Socket list is empty!\r\n" ));
}
//
// Release the socket layer synchronization
//
RESTORE_TPL ( TplPrevious );
//
// Determine if the socket was found
//
if ( NULL != pSocketPrevious ) {
pSocket->pNext = NULL;
//
// Remove the socket protocol
//
ChildHandle = pSocket->SocketProtocol.SocketHandle;
Status = gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiSocketProtocolGuid,
&pSocket->SocketProtocol,
NULL );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL | DEBUG_INFO,
"Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
ChildHandle ));
//
// Free the socket structure
//
Status = gBS->FreePool ( pSocket );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL,
"0x%08x: Free pSocket, %d bytes\r\n",
pSocket,
sizeof ( *pSocket )));
errno = 0;
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL,
"ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
pSocket,
Status ));
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
"ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
ChildHandle,
Status ));
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_INFO,
"ERROR - The socket was not in the socket list!\r\n" ));
Status = EFI_NOT_FOUND;
}
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));
}
//
// Return the errno value if possible
//
if ( NULL != pErrno ) {
*pErrno = errno;
}
//
// Return the operation status
//
DBG_EXIT_STATUS ( Status );
return Status;
}
/** /**
Get the local address. Get the local address.

View File

@ -1187,6 +1187,28 @@ EslSocketCopyFragmentedBuffer (
OUT size_t * pDataLength OUT size_t * pDataLength
); );
/**
Free the socket.
This routine frees the socket structure and handle resources.
The ::close routine calls EslServiceFreeProtocol which then calls
this routine to free the socket context structure and close the
handle.
@param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
@param [out] pErrno Address to receive the errno value upon completion.
@retval EFI_SUCCESS The socket resources were returned successfully.
**/
EFI_STATUS
EslSocketFree (
IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
IN int * pErrno
);
/** /**
Free the ESL_IO_MGMT event and structure Free the ESL_IO_MGMT event and structure

View File

@ -68,6 +68,40 @@ CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = {
}; };
/**
Free the socket resources
This releases the socket resources allocated by calling
EslServiceGetProtocol.
This routine is called from the ::close routine in BsdSocketLib
to release the socket resources.
@param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
structure
@return Value for ::errno, zero (0) indicates success.
**/
int
EslServiceFreeProtocol (
IN EFI_SOCKET_PROTOCOL * pSocketProtocol
)
{
int RetVal;
//
// Release the socket resources
//
EslSocketFree ( pSocketProtocol, &RetVal );
//
// Return the operation status
//
return RetVal;
}
/** /**
Connect to the EFI socket library Connect to the EFI socket library

View File

@ -612,6 +612,26 @@ AcceptNB (
socklen_t * address_len socklen_t * address_len
); );
/**
Free the socket resources
This releases the socket resources allocated by calling
EslServiceGetProtocol.
This routine is called from the ::close routine in BsdSocketLib
to release the socket resources.
@param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
structure
@return Value for ::errno, zero (0) indicates success.
**/
int
EslServiceFreeProtocol (
IN EFI_SOCKET_PROTOCOL * pSocketProtocol
);
/** /**
Connect to the EFI socket library Connect to the EFI socket library

View File

@ -22,6 +22,59 @@
#include <Protocol/ServiceBinding.h> #include <Protocol/ServiceBinding.h>
/**
Free the socket resources
This releases the socket resources allocated by calling
EslServiceGetProtocol.
This routine is called from the ::close routine in BsdSocketLib
to release the socket resources.
@param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
structure
@return Value for ::errno, zero (0) indicates success.
**/
int
EslServiceFreeProtocol (
IN EFI_SOCKET_PROTOCOL * pSocketProtocol
)
{
EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
int RetVal;
EFI_STATUS Status;
//
// Assume success
//
RetVal = 0;
//
// Locate the socket protocol
//
Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
NULL,
(VOID **) &pServiceBinding );
if ( !EFI_ERROR ( Status )) {
//
// Release the handle
//
Status = pServiceBinding->DestroyChild ( pServiceBinding,
pSocketProtocol->SocketHandle );
}
if ( EFI_ERROR ( Status )) {
RetVal = EIO;
}
//
// Return the operation status
//
return RetVal;
}
/** /**
Connect to the EFI socket library Connect to the EFI socket library