Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Winsock error 10093 in DLL_PROCESS_DETACH on image rundown (NT4)

197 views
Skip to first unread message

Dror Harari

unread,
Dec 13, 1999, 3:00:00 AM12/13/99
to
Hi,

I'm writing a software component which is packaged as a DLL. This component
establishes TCP/IP connections using Winsock calls (standard TCP socket
connection).

Normally, the user is closing the connections explicitly (using the
closesocket() API) but there are some cases were the program exits without
explicitly closing the connection. To avoid loosing data, I have tried to
gracefully close the connection in the DLL_PROCESS_DETACH event handling (of
DllMain).

The problem I got is that all the Winsock functions return with an error
10093 - WSANOTINITIALISED (supposedly indicating that WSAStartup() was not
called - which is obviously false). This means that I can't send data
anymore and I can't even close the socket properly. Looking at the network
packets, instead of the standard closing sequence of FIN ACK FIN ACK, all
there is is an RST packet sent out.

This problem can easily be demonstrated with a simple C program calling a
simple DLL which does the socket stuff. I have made various experimented
with no avail (e.g., doing an extra LoadLibrary on WSOCK32.DLL or doing an
extra WSAStartup() call or statically linking WSOCK32.DLL with the main).

I could not find any reference to this problem. I'd appreciate any clues or
workarounds for this problem.

TIA,

Dror

Jon Sturgeon

unread,
Dec 13, 1999, 3:00:00 AM12/13/99
to
On Mon, 13 Dec 1999 18:26:53 +0200, "Dror Harari"
<dr...@remove-to-reply.isg.co.il> wrote:

>Hi,
>
>I'm writing a software component which is packaged as a DLL. This component
>establishes TCP/IP connections using Winsock calls (standard TCP socket
>connection).
>
>Normally, the user is closing the connections explicitly (using the
>closesocket() API) but there are some cases were the program exits without
>explicitly closing the connection. To avoid loosing data, I have tried to
>gracefully close the connection in the DLL_PROCESS_DETACH event handling (of
>DllMain).
>
>The problem I got is that all the Winsock functions return with an error
>10093 - WSANOTINITIALISED (supposedly indicating that WSAStartup() was not
>called - which is obviously false).

<snip>

Maybe the calling process called WSACleanup() just before it terminated.
The act of it terminating caused your DLL to be notified through
DLL_PROCESS_DETACH, during which time you try to access the socket. But
you're already too late because WSACleanup() has already been called.

I don't see a solution to this problem. I guess you're going to have to
trust the calling application to close the socket appropriately. If it is
any consolation, since the process is terminating the local resources will
be immediately cleaned up by the OS. This doesn't help with the state of
any resources outside of the OS's control, of course, such as TCP states on
other machines.

Regards,
Jon Sturgeon


Dror Harari

unread,
Dec 14, 1999, 3:00:00 AM12/14/99
to
> Maybe the calling process called WSACleanup() just before it terminated.
> The act of it terminating caused your DLL to be notified through
> DLL_PROCESS_DETACH, during which time you try to access the socket. But
> you're already too late because WSACleanup() has already been called.

The calling process (the test program) is simply a main that calls
LoadLibary() and calls a function in the DLL. Nowhere is a call to
WSACleanup() - and that's intentional (for demonstration purpse). Who is the
mysterious entity calling WSACleanup()? And what about my WSAStartup() - why
ain't it paired with my WSACleanup()? As my DLL is linked with WSOCK32.DLL -
my DLL should be unloaded before WSOCK32.DLL!!!

The SockMain program is linked without any special libraries. The SockDll is
linked with wsock32.lib....

____________________________________________ SockMain.C ____________
#include "windows.h"
#include "stdio.h"

int main(int argc, char* argv[])
{
HINSTANCE hSockDll;
int (*fnOpenSock)(int fOpen);

hSockDll= LoadLibrary("SockDll.dll");
if (!hSockDll) { printf("Failed in LoadLibary\n"); exit(1); }

fnOpenSock = (int (*)(int)) GetProcAddress(hSockDll, "OpenSock");
if (!fnOpenSock) { printf("Failed in GetProcAddress\n"); exit(2); }

if (!fnOpenSock(1)) { printf("Failed in OpenSock(1)\n"); exit(3); }

if (argc > 1 && atoi(argv[1]) == 1)
printf("Ending program without closing socket\n");
else if (argc > 1 && atoi(argv[1]) == 2) {
printf("Unloading library without closing socket\n");
FreeLibrary(hSockDll);
}
else {
fnOpenSock(0);
printf("Ending program after closing socket\n");
}
return 0;
}
____________________________________________ SockDll.C ____________

#include "windows.h"
#include "stdio.h"
#include "winsock.h"

__declspec(dllexport) int OpenSock(int fOpen)
{
static int iSocket = -1;
struct sockaddr_in RemoteAddr;

if (fOpen) {
printf("Opening socket\n");
iSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (iSocket < 0) { printf("Failed in socket()\n"); exit(5); }

memset(&RemoteAddr, '\0', sizeof(RemoteAddr));
RemoteAddr.sin_port = htons((unsigned short)80);
RemoteAddr.sin_family = AF_INET;
RemoteAddr.sin_addr.s_addr = inet_addr("207.46.130.45"); //
www.microsoft.com

if (connect(iSocket, (struct sockaddr *)&RemoteAddr,
sizeof(RemoteAddr))) {
printf("connect failed with error %d\n", WSAGetLastError());
exit(6);
}

return (1);
}

if (iSocket > 0) {
printf("Closing socket\n");
if (closesocket(iSocket) < 0)
printf("closesocket failed with error %d\n", WSAGetLastError());

iSocket = -1;
}

return (1);
}

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
WSADATA WSAData;

switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
printf("DLL_PROCESS_ATTACH\n");
if (WSAStartup(0x0101, &WSAData)) {
printf("Failed in WSAStartup()\n");
exit(4);
}
break;

case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH\n");
OpenSock(0);
}
return TRUE;
}
________________________________________________________

Running "SockMain 1" shows the 10093 problem. Running "SockMain 2" shows the
code in DLL_PROCESS_DETACH working as intended and running "SockMain 3" is
just the normal case.

> I don't see a solution to this problem. I guess you're going to have to
> trust the calling application to close the socket appropriately. If it is
> any consolation, since the process is terminating the local resources will
> be immediately cleaned up by the OS. This doesn't help with the state of
> any resources outside of the OS's control, of course, such as TCP states
on
> other machines.

I came about this problem because my server, on an OS/390 (MVS) machine,
does not detect the socket closing unless it is done gracefully. This causes
lots of resources to be wasted on the precious server...

> Regards,
> Jon Sturgeon

Thanks for your time!

/d


userna...@my-deja.com

unread,
Jan 6, 2000, 3:00:00 AM1/6/00
to
In article <8336ha$b30$1...@news.netvision.net.il>,

"Dror Harari" <dr...@remove-to-reply.isg.co.il>
wrote:
> Hi,
>
> I'm writing a software component which is
packaged as a DLL. This component
> establishes TCP/IP connections using Winsock
calls (standard TCP socket
> connection).....
>....I have tried to

> gracefully close the connection in the
DLL_PROCESS_DETACH event handling (of
> DllMain).

I have the same problem. I saw one other posting
to a different forum with the same problem.
There was no reply. In his posting, though, he
said that it worked OK under Windows 98, but not
under NT. I used to suspect that what is
happening is NT's multi-threading is allowing the
sockets DLL to be detached before my DLL is
finished. However, the other post I mentioned
stated that he had tried statically linking the
sockets DLL. Hmmm....?

I have a DLL that communicates with a remote
process and need to terminate the remote process
cleanly when the app detaches from the DLL. I
noticed, while single-stepping through my
DLL_PROCESS_DETACH handler that the remote app
stays connected even though there is an arror on
the NT end. After the attempt to send the clean
shutdown message to the remote app fails, I go
ahead and call WSACleanup. That's when the remote
app gets a null read on its socket and
terminates. Unfortunately, this looks just like
any other error on the NT end and I would like to
be able to distinguish between errors and a
clean shutdown.

Any help would be greatly appreciated. TIA.

Dave Duperon

Here is the rest of Dror's post:


>
> The problem I got is that all the Winsock
functions return with an error
> 10093 - WSANOTINITIALISED (supposedly indicating
that WSAStartup() was not

> called - which is obviously false). This means
that I can't send data
> anymore and I can't even close the socket
properly. Looking at the network
> packets, instead of the standard closing
sequence of FIN ACK FIN ACK, all
> there is is an RST packet sent out.
>
> This problem can easily be demonstrated with a
simple C program calling a
> simple DLL which does the socket stuff. I have
made various experimented
> with no avail (e.g., doing an extra LoadLibrary
on WSOCK32.DLL or doing an
> extra WSAStartup() call or statically linking
WSOCK32.DLL with the main).
>
> I could not find any reference to this problem.
I'd appreciate any clues or
> workarounds for this problem.
>
> TIA,
>
> Dror
>
>

Sent via Deja.com http://www.deja.com/
Before you buy.

Dror Harari

unread,
Jan 6, 2000, 3:00:00 AM1/6/00
to
Hi Dave,

At this point, I have no answer, fix or workaround for this problem. I did
see it working on Win 9x but then the image rundown process on NT is
different than on Win 9x.

The main reason why this problem troubled me is that I had a server
application on MVS and when the sockets were not closed properly on the NT,
the MVS TCP/IP thought the client is still connected, hence MVS resources
leaked.

In trying to find out what the NT TCP/IP stack is doing on image rundown
when it has opened sockets, I ran some packet tracing and found that unless
an orderly closesocket() call is made BEFORE image rundown, the NT TCP/IP
stack does not close the connection with the FIN-ACK-FIN-ACK sequence, but
instead just sends a single RST packet to the server. On the MVS, the TCP/IP
stack was of a somewhat old version and was not closing the socket upon RST
(or it could also be that the RST packet did not make it to the MVS, but
that's less likely).

My experience is, therefore, that having my protocl depend only on breaking
the socket for a session closing indication was OK and other than the bug in
the MVS TCP/IP stack, nothing significant was lost. Checking on the remote
for a client disconnect is easy and portable. If you want to get a positive
shutdown indication, you may assume that unless you get a clean shutdown
message, there was an error...

Regards,

/d
ISG Ltd.

p.s., I doubt that the image rundown is made in multi-threading way because
there is a clear inter-dll dependency and if a dependent dll is yanked out
of existence before the dll using it does, then a glorious GPE is bound to
appear.
----- Original Message -----
From: "Dave Duperon"
To: "Dror"
Sent: Thursday, January 06, 2000 1:35 AM
Subject: Winsock error 10093 in DLL_PROCESS_DETACH


> Hello. I saw your posting to comp.os.ms-windows.networking.tcp-ip,
> posted on 12/13/99. I am hoping you have found an answer because I have
> the same problem; "Sockets system not initialized" during process dll
> detach. I have not found any information yet on a fix or workaround. I
> did see one other posting to a different forum with the same problem.


> There was no reply. In his posting, though, he said that it worked OK
> under Windows 98, but not under NT. I used to suspect that what is
> happening is NT's multi-threading is allowing the sockets DLL to be

> detached before my DLL is finished. Howver, the other post I mentioned


> stated that he had tried statically linking the sockets DLL. Hmmm....
>

> I have a DLL that communicates with a remote process and need to
> terminate the remote process cleanly when the app detaches from the
> DLL. I noticed, while single-stepping through my DLL_PROCESS_DETACH
> handler that the remote app stays connected even though there is an
> arror on the NT end. After the attempt to send the clean shutdown
> message to the remote app fails, I go ahead and call WSACleanup. That's
> when the remote app gets a null read on its socket and terminates.
> Unfortunately, this looks just like any other error on the NT end and I
> would like to be able to distinguish between errors and a clean
> shutdown.
>

> Any help you might provide would be greatly appreciated. TIA.
>
> Dave Duperon
> Fluke Corporation
>
>

Alun Jones

unread,
Jan 6, 2000, 3:00:00 AM1/6/00
to
In article <851vv2$aj$1...@news.netvision.net.il>, "Dror Harari"
<dr...@remove-to-reply.isg.co.il> wrote:
> At this point, I have no answer, fix or workaround for this problem. I did
> see it working on Win 9x but then the image rundown process on NT is
> different than on Win 9x.

Check out the Winsock 2 mailing list archive at http://www.stardust.com for
more details on the behaviour of DLL_PROCESS_DETACH and sockets. Basically,
IIRC, by the time your DLL is unloading in this section, the Winsock DLL has
usually already closed its sockets, and may not even be loaded any more.

Alun.
~~~~

--
Texas Imperial Software | Try WFTPD, the Windows FTP Server. Find it
1602 Harvest Moon Place | at web site http://www.wftpd.com or email
Cedar Park TX 78613 | us at al...@texis.com. VISA / MC accepted.
Fax +1 (512) 378 3246 | NT based ISPs, be sure to read details of
Phone +1 (512) 378 3246 | WFTPD Pro, NT service version - $100.
*WFTPD and WFTPD Pro now available as native Alpha versions for NT*

Dror Harari

unread,
Jan 13, 2000, 3:00:00 AM1/13/00
to
"Alun Jones" <al...@texis.com> wrote in message
news:852e2q$80b0...@news.io.com...
>...

> Check out the Winsock 2 mailing list archive at http://www.stardust.com
for
> more details on the behaviour of DLL_PROCESS_DETACH and sockets.
Basically,
> IIRC, by the time your DLL is unloading in this section, the Winsock DLL
has
> usually already closed its sockets, and may not even be loaded any more.

The main problem I see with that description is as follows: I have a DLL
CompA statically linked with CompB which is statically linked with
WSOCK32.DLL (when I say 'statically linked' I mean linked with the export
library so that Windows knows that CompA depends on CompB who in turn
depends on WSOCK32.DLL).

Now for the PROCESS_DETACH event to be meaningful, one must be able to
assume that the underlying DLLs - most notably the statically linked ones -
are not getting the PROCESS_DETACH earlier. Otherwise, what can you really
do in that event? This is more of an issue because nowdays you are expected
to be able to gracefully be unloaded from memory, freeing all the resources
you used (not as a part of process termination).

The MSDN documentation describes the limitations on what you can call within
the PROCESS_ATTACH event but I found no reference to what can be done on the
PROCESS_DETACH event, nor on the process termination sequence. If anyone
knows where this kind of information can be found, please let me know.

Thanks,

/d

"Alun Jones" <al...@texis.com> wrote in message
news:852e2q$80b0...@news.io.com...

Alun Jones

unread,
Jan 14, 2000, 3:00:00 AM1/14/00
to
In article <85ldll$li6$1...@news.netvision.net.il>, "Dror Harari"
<dr...@remove-to-reply.isg.co.il> wrote:
> The MSDN documentation describes the limitations on what you can call within
> the PROCESS_ATTACH event but I found no reference to what can be done on the
> PROCESS_DETACH event, nor on the process termination sequence. If anyone
> knows where this kind of information can be found, please let me know.

Go searching through the knowledge base for "DLL_PROCESS_DETACH", and you'll
find a few items referring to the lack of any ordering of which DLLs get
called with DLL_PROCESS_DETACH. Essentially, you shouldn't call one DLL
from another in the DLL_PROCESS_DETACH section.

0 new messages