Line data Source code
1 : #include "common.h"
2 :
3 : #if HAVE_UNISTD_H
4 : #include <unistd.h>
5 : #endif /* HAVE_UNISTD_H */
6 :
7 : #include <freetds/time.h>
8 :
9 : #if HAVE_SYS_SOCKET_H
10 : #include <sys/socket.h>
11 : #endif /* HAVE_SYS_SOCKET_H */
12 :
13 : #if HAVE_SYS_STAT_H
14 : #include <sys/stat.h>
15 : #endif /* HAVE_SYS_STAT_H */
16 :
17 : #if HAVE_SYS_IOCTL_H
18 : #include <sys/ioctl.h>
19 : #endif /* HAVE_SYS_IOCTL_H */
20 :
21 : #if HAVE_SYS_WAIT_H
22 : #include <sys/wait.h>
23 : #endif /* HAVE_SYS_WAIT_H */
24 :
25 : #include <freetds/utils.h>
26 :
27 : /*
28 : * test error on connection close
29 : * With a trick we simulate a connection close then we try to
30 : * prepare or execute a query. This should fail and return an error message.
31 : */
32 :
33 : #if HAVE_FSTAT && defined(S_IFSOCK)
34 :
35 : static int end_socket = -1;
36 :
37 : static int
38 20 : shutdown_last_socket(void)
39 : {
40 20 : TDS_SYS_SOCKET max_socket = odbc_find_last_socket();
41 : TDS_SYS_SOCKET sockets[2];
42 :
43 20 : if (max_socket < 0)
44 : return 0;
45 :
46 : /* replace socket with a new one */
47 20 : if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
48 : return 0;
49 :
50 20 : tds_socket_set_nosigpipe(sockets[0], 1);
51 :
52 : /* substitute socket */
53 20 : close(max_socket);
54 20 : dup2(sockets[0], max_socket);
55 :
56 : /* close connection */
57 20 : close(sockets[0]);
58 20 : end_socket = sockets[1];
59 20 : return 1;
60 : }
61 :
62 : static int
63 20 : Test(int direct)
64 : {
65 : SQLTCHAR buf[256];
66 : SQLTCHAR sqlstate[6];
67 : time_t start_time, end_time;
68 :
69 20 : odbc_mark_sockets_opened();
70 20 : odbc_connect();
71 :
72 20 : if (!shutdown_last_socket()) {
73 0 : fprintf(stderr, "Error shutting down connection\n");
74 0 : return 1;
75 : }
76 :
77 20 : CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 10, SQL_IS_UINTEGER, "S");
78 :
79 20 : alarm(30);
80 20 : start_time = time(NULL);
81 20 : if (direct) {
82 10 : CHKExecDirect(T("SELECT 1"), SQL_NTS, "E");
83 : } else {
84 : SQLSMALLINT cols;
85 :
86 : /* force dialog with server */
87 10 : if (CHKPrepare(T("SELECT 1"), SQL_NTS, "SE") == SQL_SUCCESS)
88 8 : CHKNumResultCols(&cols, "E");
89 : }
90 20 : end_time = time(NULL);
91 20 : alarm(0);
92 :
93 20 : memset(sqlstate, 'X', sizeof(sqlstate));
94 20 : CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, buf, TDS_VECTOR_SIZE(buf), NULL, "SI");
95 20 : sqlstate[5] = 0;
96 20 : printf("Message: %s - %s\n", C(sqlstate), C(buf));
97 20 : if (strcmp(C(sqlstate), "HYT00") || !strstr(C(buf), "Timeout")) {
98 0 : fprintf(stderr, "Invalid timeout message\n");
99 0 : return 1;
100 : }
101 20 : if (end_time - start_time < 10 || end_time - start_time > 26) {
102 0 : fprintf(stderr, "Unexpected connect timeout (%d)\n", (int) (end_time - start_time));
103 0 : return 1;
104 : }
105 :
106 20 : odbc_disconnect();
107 :
108 20 : if (end_socket >= 0)
109 20 : close(end_socket);
110 :
111 20 : printf("Done.\n");
112 20 : return 0;
113 : }
114 :
115 10 : TEST_MAIN()
116 : {
117 10 : if (Test(0) || Test(1))
118 : return 1;
119 : return 0;
120 : }
121 :
122 : #else
123 : TEST_MAIN()
124 : {
125 : printf("Not possible for this platform.\n");
126 : odbc_test_skipped();
127 : return 0;
128 : }
129 : #endif
|