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 16 : shutdown_last_socket(void)
39 : {
40 16 : TDS_SYS_SOCKET max_socket = odbc_find_last_socket();
41 : TDS_SYS_SOCKET sockets[2];
42 :
43 16 : if (max_socket < 0)
44 : return 0;
45 :
46 : /* replace socket with a new one */
47 16 : if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
48 : return 0;
49 :
50 16 : tds_socket_set_nosigpipe(sockets[0], 1);
51 :
52 : /* substitute socket */
53 16 : close(max_socket);
54 16 : dup2(sockets[0], max_socket);
55 :
56 : /* close connection */
57 16 : close(sockets[0]);
58 16 : end_socket = sockets[1];
59 16 : return 1;
60 : }
61 :
62 : static int
63 16 : Test(int direct)
64 : {
65 : SQLTCHAR buf[256];
66 : SQLTCHAR sqlstate[6];
67 : time_t start_time, end_time;
68 :
69 16 : odbc_mark_sockets_opened();
70 16 : odbc_connect();
71 :
72 16 : if (!shutdown_last_socket()) {
73 0 : fprintf(stderr, "Error shutting down connection\n");
74 0 : return 1;
75 : }
76 :
77 16 : CHKSetStmtAttr(SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER) 10, SQL_IS_UINTEGER, "S");
78 :
79 16 : alarm(30);
80 16 : start_time = time(NULL);
81 16 : if (direct) {
82 8 : CHKExecDirect(T("SELECT 1"), SQL_NTS, "E");
83 : } else {
84 : SQLSMALLINT cols;
85 : /* force dialog with server */
86 8 : if (CHKPrepare(T("SELECT 1"), SQL_NTS, "SE") == SQL_SUCCESS)
87 6 : CHKNumResultCols(&cols, "E");
88 : }
89 16 : end_time = time(NULL);
90 16 : alarm(0);
91 :
92 16 : memset(sqlstate, 'X', sizeof(sqlstate));
93 16 : CHKGetDiagRec(SQL_HANDLE_STMT, odbc_stmt, 1, sqlstate, NULL, buf, TDS_VECTOR_SIZE(buf), NULL, "SI");
94 16 : sqlstate[5] = 0;
95 16 : printf("Message: %s - %s\n", C(sqlstate), C(buf));
96 16 : if (strcmp(C(sqlstate), "HYT00") || !strstr(C(buf), "Timeout")) {
97 0 : fprintf(stderr, "Invalid timeout message\n");
98 0 : return 1;
99 : }
100 16 : if (end_time - start_time < 10 || end_time - start_time > 26) {
101 0 : fprintf(stderr, "Unexpected connect timeout (%d)\n", (int) (end_time - start_time));
102 0 : return 1;
103 : }
104 :
105 16 : odbc_disconnect();
106 :
107 16 : if (end_socket >= 0)
108 16 : close(end_socket);
109 :
110 16 : printf("Done.\n");
111 16 : return 0;
112 : }
113 :
114 : int
115 8 : main(void)
116 : {
117 8 : odbc_use_version3 = 1;
118 :
119 8 : if (Test(0) || Test(1))
120 : return 1;
121 : return 0;
122 : }
123 :
124 : #else
125 : int
126 : main(void)
127 : {
128 : printf("Not possible for this platform.\n");
129 : odbc_test_skipped();
130 : return 0;
131 : }
132 : #endif
|