Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Christian Butz
VTK
Commits
bafa6bf9
Commit
bafa6bf9
authored
Apr 15, 2011
by
Burlen Loring
Committed by
David Partyka
Apr 21, 2011
Browse files
Fix bug 12087 vtkSocket does not restart interupted call.
Change-Id: I7d98c21afbfa44ac139c58ef53c097492e43846a
parent
e6760e8b
Changes
2
Hide whitespace changes
Inline
Side-by-side
Common/vtkSocket.cxx
View file @
bafa6bf9
...
...
@@ -16,6 +16,10 @@
#include "vtkObjectFactory.h"
#if defined(__BORLANDC__)
# pragma warn -8012
/* signed/unsigned comparison */
#endif
// The VTK_SOCKET_FAKE_API definition is given to the compiler
// command line by CMakeLists.txt if there is no real sockets
// interface available. When this macro is defined we simply make
...
...
@@ -38,25 +42,86 @@
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#endif
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
// TODO : document why we restrict to v1.1
#define WSA_VERSION MAKEWORD(1,1)
#define vtkCloseSocketMacro(sock) (closesocket(sock))
#define vtkCloseSocketMacro(sock) (closesocket(sock))
#define vtkErrnoMacro (WSAGetLastError())
#define vtkStrerrorMacro(_num) (wsaStrerror(_num))
#define vtkSocketErrorIdMacro(_id) (WSA##_id)
#define vtkSocketErrorReturnMacro (SOCKET_ERROR)
#else
#define vtkCloseSocketMacro(sock) (close(sock))
#define vtkCloseSocketMacro(sock) (close(sock))
#define vtkErrnoMacro (errno)
#define vtkStrerrorMacro(_num) (strerror(_num))
#define vtkSocketErrorIdMacro(_id) (_id)
#define vtkSocketErrorReturnMacro (-1)
#endif
#if defined(__BORLANDC__)
# pragma warn -8012
/* signed/unsigned comparison */
// This macro wraps a system function call(_call),
// restarting the call in case it was interrupted
// by a signal (EINTR).
#define vtkRestartInterruptedSystemCallMacro(_call,_ret)\
do \
{ \
(_ret)=(_call); \
} \
while (((_ret)==vtkSocketErrorReturnMacro) \
&& (vtkErrnoMacro==vtkSocketErrorIdMacro(EINTR)));
// use when _str may be a null pointer but _fallback is not.
#define vtkSafeStrMacro(_str,_fallback) ((_str)?(_str):(_fallback))
// convert error number to string and report via vtkErrorMacro.
#define vtkSocketErrorMacro(_eno, _message) \
vtkErrorMacro( \
<< (_message) \
<< " " \
<< vtkSafeStrMacro( \
vtkStrerrorMacro(_eno), \
"unknown error") \
<< ".");
// convert error number to string and report via vtkGenericWarningMacro
#define vtkSocketGenericErrorMacro(_message) \
vtkGenericWarningMacro( \
<< (_message) \
<< " " \
<< vtkSafeStrMacro( \
vtkStrerrorMacro(vtkErrnoMacro), \
"unknown error") \
<< ".");
// on windows strerror doesn't handle socket error codes
#if defined(_WIN32) && !defined(__CYGWIN__)
static
const
char
*
wsaStrerror
(
int
wsaeid
)
{
static
char
buf
[
256
]
=
{
'\0'
};
int
ok
;
ok
=
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM
,
0
,
wsaeid
,
0
,
buf
,
256
,
0
);
if
(
!
ok
)
{
return
0
;
}
return
buf
;
}
#endif
//-----------------------------------------------------------------------------
vtkSocket
::
vtkSocket
()
{
this
->
SocketDescriptor
=
-
1
;
}
//-----------------------------------------------------------------------------
...
...
@@ -73,19 +138,39 @@ vtkSocket::~vtkSocket()
int
vtkSocket
::
CreateSocket
()
{
#ifndef VTK_SOCKET_FAKE_API
int
sock
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
int
sock
;
vtkRestartInterruptedSystemCallMacro
(
socket
(
AF_INET
,
SOCK_STREAM
,
0
),
sock
);
if
(
sock
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to socket."
);
return
-
1
;
}
// Elimate windows 0.2 second delay sending (buffering) data.
int
on
=
1
;
if
(
setsockopt
(
sock
,
IPPROTO_TCP
,
TCP_NODELAY
,
(
char
*
)
&
on
,
sizeof
(
on
)))
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
sock
,
IPPROTO_TCP
,
TCP_NODELAY
,
(
char
*
)
&
on
,
sizeof
(
on
)),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to setsockopt."
);
return
-
1
;
}
return
sock
;
#else
return
-
1
;
#endif
}
//-----------------------------------------------------------------------------
void
vtkSocket
::
CloseSocket
()
{
this
->
CloseSocket
(
this
->
SocketDescriptor
);
this
->
SocketDescriptor
=
-
1
;
}
//-----------------------------------------------------------------------------
int
vtkSocket
::
BindSocket
(
int
socketdescriptor
,
int
port
)
{
...
...
@@ -97,16 +182,31 @@ int vtkSocket::BindSocket(int socketdescriptor, int port)
server
.
sin_port
=
htons
(
port
);
// Allow the socket to be bound to an address that is already in use
int
opt
=
1
;
int
iErr
=~
vtkSocketErrorReturnMacro
;
#ifdef _WIN32
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
opt
,
sizeof
(
int
));
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,(
char
*
)
&
opt
,
sizeof
(
int
)),
iErr
);
#elif defined(VTK_HAVE_SO_REUSEADDR)
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
void
*
)
&
opt
,
sizeof
(
int
));
vtkRestartInterruptedSystemCallMacro
(
setsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_REUSEADDR
,(
char
*
)
&
opt
,
sizeof
(
int
)),
iErr
);
#endif
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to setsockopt."
);
return
-
1
;
}
if
(
bind
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
server
),
sizeof
(
server
))
)
vtkRestartInterruptedSystemCallMacro
(
bind
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
server
),
sizeof
(
server
)),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to bind."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
...
...
@@ -121,9 +221,20 @@ int vtkSocket::Accept(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
return
accept
(
socketdescriptor
,
0
,
0
);
int
newDescriptor
;
vtkRestartInterruptedSystemCallMacro
(
accept
(
socketdescriptor
,
0
,
0
),
newDescriptor
);
if
(
newDescriptor
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to accept."
);
return
-
1
;
}
return
newDescriptor
;
#else
static_cast
<
void
>
(
socketdescriptor
);
return
-
1
;
...
...
@@ -136,9 +247,19 @@ int vtkSocket::Listen(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
return
listen
(
socketdescriptor
,
1
);
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
listen
(
socketdescriptor
,
1
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to listen."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
return
-
1
;
...
...
@@ -151,32 +272,54 @@ int vtkSocket::SelectSocket(int socketdescriptor, unsigned long msec)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
// invalid socket
descriptor.
vtkErrorMacro
(
"Invalid
descriptor.
"
);
return
-
1
;
}
fd_set
rset
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
int
res
;
do
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
(
msec
%
1000
)
*
1000
;
tvalptr
=
&
tval
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
(
msec
%
1000
)
*
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
FD_SET
(
socketdescriptor
,
&
rset
);
// block until socket is readable.
res
=
select
(
socketdescriptor
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
}
FD_ZERO
(
&
rset
);
FD_SET
(
socketdescriptor
,
&
rset
);
int
res
=
select
(
socketdescriptor
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
if
(
res
==
0
)
while
((
res
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
))
);
if
(
res
==
0
)
{
return
0
;
//for time limit expire
// time out
return
0
;
}
if
(
res
<
0
||
!
(
FD_ISSET
(
socketdescriptor
,
&
rset
))
)
else
if
(
res
==
vtkSocketErrorReturnMacro
)
{
// Some error.
// error in the call
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to select."
);
return
-
1
;
}
else
if
(
!
FD_ISSET
(
socketdescriptor
,
&
rset
))
{
vtkErrorMacro
(
"Socket error in select. Descriptor not selected."
);
return
-
1
;
}
// NOTE: not checking for pending errors,these will be handled
// in the next call to read/recv
// The indicated socket has some activity on it.
return
1
;
#else
...
...
@@ -191,50 +334,70 @@ int vtkSocket::SelectSockets(const int* sockets_to_select, int size,
unsigned
long
msec
,
int
*
selected_index
)
{
#ifndef VTK_SOCKET_FAKE_API
int
i
;
int
max_fd
=
-
1
;
*
selected_index
=
-
1
;
if
(
size
<
0
)
if
(
size
<
0
)
{
vtkGenericWarningMacro
(
"Can't select fewer than 0."
);
return
-
1
;
}
fd_set
rset
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
msec
%
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
for
(
i
=
0
;
i
<
size
;
i
++
)
int
res
=
-
1
;
do
{
FD_SET
(
sockets_to_select
[
i
],
&
rset
);
max_fd
=
(
sockets_to_select
[
i
]
>
max_fd
)
?
sockets_to_select
[
i
]
:
max_fd
;
struct
timeval
tval
;
struct
timeval
*
tvalptr
=
0
;
if
(
msec
>
0
)
{
tval
.
tv_sec
=
msec
/
1000
;
tval
.
tv_usec
=
msec
%
1000
;
tvalptr
=
&
tval
;
}
FD_ZERO
(
&
rset
);
int
max_fd
=
-
1
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
FD_SET
(
sockets_to_select
[
i
],
&
rset
);
max_fd
=
(
sockets_to_select
[
i
]
>
max_fd
?
sockets_to_select
[
i
]
:
max_fd
);
}
// block until one socket is ready to read.
res
=
select
(
max_fd
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
}
int
res
=
select
(
max_fd
+
1
,
&
rset
,
0
,
0
,
tvalptr
);
if
(
res
==
0
)
while
((
res
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
)));
if
(
res
==
0
)
{
return
0
;
//Timeout
// time out
return
0
;
}
if
(
res
<
0
)
else
if
(
res
==
vtkSocketErrorReturnMacro
)
{
// SelectSocket error.
// error in the call
vtkSocketGenericErrorMacro
(
"Socket error in call to select."
);
return
-
1
;
}
//
check which
socket has some activity.
for
(
i
=
0
;
i
<
size
;
i
++
)
//
find the first
socket
which
has some activity.
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
if
(
FD_ISSET
(
sockets_to_select
[
i
],
&
rset
)
)
{
// NOTE: not checking for pending errors, these
// will be handled in the next call to read/recv
*
selected_index
=
i
;
return
1
;
}
}
// no activity on any of the sockets
vtkGenericWarningMacro
(
"Socket error in select. No descriptor selected."
);
return
-
1
;
#else
static_cast
<
void
>
(
sockets_to_select
);
...
...
@@ -251,6 +414,7 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
-
1
;
}
...
...
@@ -261,10 +425,9 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
unsigned
long
addr
=
inet_addr
(
hostName
);
hp
=
gethostbyaddr
((
char
*
)
&
addr
,
sizeof
(
addr
),
AF_INET
);
}
if
(
!
hp
)
{
//
vtkErrorMacro("Unknown host: " << hostName);
vtkErrorMacro
(
"Unknown host: "
<<
hostName
);
return
-
1
;
}
...
...
@@ -273,8 +436,53 @@ int vtkSocket::Connect(int socketdescriptor, const char* hostName, int port)
memcpy
(
&
name
.
sin_addr
,
hp
->
h_addr
,
hp
->
h_length
);
name
.
sin_port
=
htons
(
port
);
return
connect
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
name
),
sizeof
(
name
));
int
iErr
=
connect
(
socketdescriptor
,
reinterpret_cast
<
sockaddr
*>
(
&
name
),
sizeof
(
name
));
if
(
(
iErr
==
vtkSocketErrorReturnMacro
)
&&
(
vtkErrnoMacro
==
vtkSocketErrorIdMacro
(
EINTR
))
)
{
// Restarting an interrupted connect call only works on linux,
// other unix require a call to select which blocks until the
// connection is complete.
// See Stevens 2d ed, 15.4 p413, "interrupted connect"
iErr
=
this
->
SelectSocket
(
socketdescriptor
,
0
);
if
(
iErr
==
-
1
)
{
// SelectSocket doesn't test for pending errors.
int
pendingErr
;
#if defined(VTK_HAVE_GETSOCKNAME_WITH_SOCKLEN_T)
socklen_t
pendingErrLen
=
sizeof
(
pendingErr
);
#else
int
pendingErrLen
=
sizeof
(
pendingErr
);
#endif
vtkRestartInterruptedSystemCallMacro
(
getsockopt
(
socketdescriptor
,
SOL_SOCKET
,
SO_ERROR
,
(
char
*
)
&
pendingErr
,
&
pendingErrLen
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to getsockopt."
);
return
-
1
;
}
else
if
(
pendingErr
)
{
vtkSocketErrorMacro
(
pendingErr
,
"Socket error pending from call to connect."
);
return
-
1
;
}
}
}
else
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to connect."
);
return
-
1
;
}
return
0
;
#else
static_cast
<
void
>
(
socketdescriptor
);
static_cast
<
void
>
(
hostName
);
...
...
@@ -294,8 +502,15 @@ int vtkSocket::GetPort(int sock)
#else
int
sizebuf
=
sizeof
(
sockinfo
);
#endif
if
(
getsockname
(
sock
,
reinterpret_cast
<
sockaddr
*>
(
&
sockinfo
),
&
sizebuf
)
!=
0
)
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
getsockname
(
sock
,
reinterpret_cast
<
sockaddr
*>
(
&
sockinfo
),
&
sizebuf
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to getsockname."
);
return
0
;
}
return
ntohs
(
sockinfo
.
sin_port
);
...
...
@@ -311,9 +526,18 @@ void vtkSocket::CloseSocket(int socketdescriptor)
#ifndef VTK_SOCKET_FAKE_API
if
(
socketdescriptor
<
0
)
{
vtkErrorMacro
(
"Invalid descriptor."
);
return
;
}
vtkCloseSocketMacro
(
socketdescriptor
);
int
iErr
;
vtkRestartInterruptedSystemCallMacro
(
vtkCloseSocketMacro
(
socketdescriptor
),
iErr
);
if
(
iErr
==
vtkSocketErrorReturnMacro
)
{
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to close/closesocket."
);
}
#else
static_cast
<
void
>
(
socketdescriptor
);
return
;
...
...
@@ -326,6 +550,7 @@ int vtkSocket::Send(const void* data, int length)
#ifndef VTK_SOCKET_FAKE_API
if
(
!
this
->
GetConnected
())
{
vtkErrorMacro
(
"Not connected."
);
return
0
;
}
if
(
length
==
0
)
...
...
@@ -337,22 +562,19 @@ int vtkSocket::Send(const void* data, int length)
int
total
=
0
;
do
{
int
flags
;
#if defined(_WIN32) && !defined(__CYGWIN__)
flags
=
0
;
#else
// disabling, since not present on SUN.
// flags = MSG_NOSIGNAL; //disable signal on Unix boxes.
flags
=
0
;
#endif
int
n
=
send
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
flags
);
if
(
n
<
0
)
int
flags
=
0
;
int
nSent
;
vtkRestartInterruptedSystemCallMacro
(
send
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
flags
),
nSent
);
if
(
nSent
==
vtkSocketErrorReturnMacro
)
{
vtkErrorMacro
(
"Socket
E
rror
: Send faile
d."
);
vtk
Socket
ErrorMacro
(
vtkErrnoMacro
,
"Socket
e
rror
in call to sen
d."
);
return
0
;
}
total
+=
n
;
total
+=
n
Sent
;
}
while
(
total
<
length
);
return
1
;
#else
static_cast
<
void
>
(
data
);
...
...
@@ -367,39 +589,49 @@ int vtkSocket::Receive(void* data, int length, int readFully/*=1*/)
#ifndef VTK_SOCKET_FAKE_API
if
(
!
this
->
GetConnected
())
{
vtkErrorMacro
(
"Not connected."
);
return
0
;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
int
trys
=
0
;
#endif
char
*
buffer
=
reinterpret_cast
<
char
*>
(
data
);
int
total
=
0
;
do
{
#if defined(_WIN32) && !defined(__CYGWIN__)
int
trys
=
0
;
#endif
int
n
=
recv
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
0
);
if
(
n
<
1
)
int
nRecvd
;
vtkRestartInterruptedSystemCallMacro
(
recv
(
this
->
SocketDescriptor
,
buffer
+
total
,
length
-
total
,
0
),
nRecvd
);
if
(
nRecvd
==
0
)
{
// peer shut down
return
0
;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
if
((
nRecvd
==
vtkSocketErrorReturnMacro
)
&&
(
WSAGetLastError
()
==
WSAENOBUFS
))
{
// On long messages, Windows recv sometimes fails with WSAENOBUFS, but
// will work if you try again.
int
error
=
WSAGetLastError
();
if
((
error
==
WSAENOBUFS
)
&&
(
trys
++
<
1000
))
if
((
trys
++
<
1000
))
{
Sleep
(
1
);
continue
;
}
#else
// On unix, a recv may be interrupted by a signal. In this case we should
// retry.
int
errorNumber
=
errno
;
if
(
errorNumber
==
EINTR
)
continue
;
#endif
vtkErrorMacro
(
"Socket Error: Receive failed."
);
vtkSocketErrorMacro
(
vtkErrnoMacro
,
"Socket error in call to recv."
);
return
0
;
}
total
+=
n
;
}
while
(
readFully
&&
total
<
length
);
#endif
total
+=
nRecvd
;
}
while
(
readFully
&&
(
total
<
length
));
return
total
;
#else
static_cast
<
void
>
(
data
);
...
...
Common/vtkSocket.h
View file @
bafa6bf9
...
...
@@ -36,7 +36,7 @@ public:
// Description:
// Close the socket.
void
CloseSocket
()
{
this
->
CloseSocket
(
this
->
SocketDescriptor
);}
void
CloseSocket
()
;
// ------ Communication API ---
// Description:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment