2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-04 16:25:17 +00:00

socket-util: Report POLLHUP as an error while connection completion checking.

Otherwise failed non-blocking connection could be reported as
connected. This causes errors in all following operations with the
socket.

At least this is true on FreeBSD, where POLLHUP could be set without
POLLERR.

For example, stream_open_block() tests fails with the following error
reporting successful connection to the 'WRONG_PORT':

  ./ovsdb-idl.at:1817:
             $PYTHON2 $srcdir/test-stream.py tcp:127.0.0.1:$WRONG_PORT
  stdout:
  ./ovsdb-idl.at:1817: exit code was 0, expected 1
  2399. ovsdb-idl.at:1817:  FAILED (ovsdb-idl.at:1817)

Also added new tests to track this issue in C library:
  'Check Stream open block - C - tcp'
  'Check Stream open block - C - tcp6'

CC: Numan Siddique <nusiddiq@redhat.com>
Fixes: c1aa16d191 ("ovs python: ovs.stream.open_block() returns success even if the remote is unreachable")
Fixes: d6cedfd9d2 ("socket-util: Avoid using SO_ERROR.")
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Ilya Maximets
2018-12-21 16:09:50 +03:00
committed by Ben Pfaff
parent 05aec0e5a7
commit cfef5ae8f0
6 changed files with 70 additions and 2 deletions

View File

@@ -285,7 +285,7 @@ check_connection_completion(int fd)
}
#endif
if (retval == 1) {
if (pfd.revents & POLLERR) {
if (pfd.revents & (POLLERR | POLLHUP)) {
ssize_t n = send(fd, "", 1, 0);
if (n < 0) {
return sock_errno();

View File

@@ -178,7 +178,7 @@ def check_connection_completion(sock):
pfds = p.poll(0)
if len(pfds) == 1:
revents = pfds[0][1]
if revents & ovs.poller.POLLERR:
if revents & ovs.poller.POLLERR or revents & ovs.poller.POLLHUP:
try:
# The following should raise an exception.
sock.send("\0".encode(), socket.MSG_DONTWAIT)

1
tests/.gitignore vendored
View File

@@ -51,6 +51,7 @@
/test-sha1
/test-skiplist
/test-stp
/test-stream
/test-strtok_r
/test-timeval
/test-type-props

View File

@@ -436,6 +436,10 @@ endif
tests_ovstest_LDADD = lib/libopenvswitch.la ovn/lib/libovn.la
noinst_PROGRAMS += tests/test-stream
tests_test_stream_SOURCES = tests/test-stream.c
tests_test_stream_LDADD = lib/libopenvswitch.la
noinst_PROGRAMS += tests/test-strtok_r
tests_test_strtok_r_SOURCES = tests/test-strtok_r.c

View File

@@ -1785,6 +1785,23 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re
008: End test
]])
m4_define([CHECK_STREAM_OPEN_BLOCK],
[AT_SETUP([Check Stream open block - C - $1])
AT_SKIP_IF([test "$1" = "tcp6" && test "$IS_WIN32" = "yes"])
AT_SKIP_IF([test "$1" = "tcp6" && test "$HAVE_IPV6" = "no"])
AT_KEYWORDS([Check Stream open block $1])
AT_CHECK([ovsdb_start_idltest "ptcp:0:$2"])
PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
WRONG_PORT=$(($TCP_PORT+1))
AT_CHECK([test-stream tcp:$2:$TCP_PORT], [0], [ignore])
AT_CHECK([test-stream tcp:$2:$WRONG_PORT], [1], [ignore], [ignore])
OVSDB_SERVER_SHUTDOWN
AT_CHECK([test-stream tcp:$2:$TCP_PORT], [1], [ignore], [ignore])
AT_CLEANUP])
CHECK_STREAM_OPEN_BLOCK([tcp], [127.0.0.1])
CHECK_STREAM_OPEN_BLOCK([tcp6], [[[::1]]])
m4_define([CHECK_STREAM_OPEN_BLOCK_PY],
[AT_SETUP([$1])
AT_SKIP_IF([test $2 = no])

46
tests/test-stream.c Normal file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018 Ilya Maximets <i.maximets@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include "fatal-signal.h"
#include "openvswitch/vlog.h"
#include "stream.h"
#include "util.h"
VLOG_DEFINE_THIS_MODULE(test_stream);
int
main(int argc, char *argv[])
{
int error;
struct stream *stream;
fatal_ignore_sigpipe();
set_program_name(argv[0]);
if (argc < 2) {
ovs_fatal(0, "usage: %s REMOTE", argv[0]);
}
error = stream_open_block(stream_open(argv[1], &stream, DSCP_DEFAULT),
&stream);
if (error) {
VLOG_ERR("stream_open_block(%s) failure: %s",
argv[1], ovs_strerror(error));
}
return (error || !stream) ? 1 : 0;
}