Merge ~info-martin-konrad/epics-base:fix-log-issues into ~epics-core/epics-base/+git/epics-base:3.15
- Git
- lp:~info-martin-konrad/epics-base
- fix-log-issues
- Merge into 3.15
Status: | Merged |
---|---|
Approved by: | Andrew Johnson |
Approved revision: | e6914f3b8089a417c9efc31940906854be182e6b |
Merged at revision: | 9df39475cd70ac8449cbc4406c08766fc8d9c0cc |
Proposed branch: | ~info-martin-konrad/epics-base:fix-log-issues |
Merge into: | ~epics-core/epics-base/+git/epics-base:3.15 |
Diff against target: |
708 lines (+238/-153) 11 files modified
src/ioc/misc/dbCore.dbd (+3/-0) src/libCom/log/iocLog.c (+25/-0) src/libCom/log/logClient.c (+103/-152) src/libCom/log/logClient.h (+0/-1) src/libCom/osi/Makefile (+1/-0) src/libCom/osi/os/Darwin/osdSockUnsentCount.c (+19/-0) src/libCom/osi/os/Linux/osdSockUnsentCount.c (+19/-0) src/libCom/osi/os/WIN32/osdSockUnsentCount.c (+26/-0) src/libCom/osi/os/default/osdSockUnsentCount.c (+15/-0) src/libCom/osi/os/iOS/osdSockUnsentCount.c (+19/-0) src/libCom/osi/osiSock.h (+8/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
mdavidsaver | Approve | ||
Review via email: mp+375509@code.launchpad.net |
Commit message
Description of the change
Fix lp:1841608 + some other logging issues (cherry-picked from 7.0 branch).
mdavidsaver (mdavidsaver) wrote : | # |
mdavidsaver (mdavidsaver) wrote : | # |
appveyor test build fails, looks like a missing header. I recall seeing this before, so maybe a missing patch.
https:/
Freddie Akeroyd (freddie-akeroyd) wrote : | # |
I think the header is there, two possibilities:
The function wasn't available in original W10 so may need to check windows DDK version too i.e. add
#if NTDDI_VERSION >= NTDDI_WIN10_RS2
to the other macro checks.
The failed build is also an old Visual Studio, maybe the option isn't enabled in the MS header for that old a VC? If so then there would need to be a check on the value of the _MSC_VER macro too.
Freddie Akeroyd (freddie-akeroyd) wrote : | # |
Or maybe just
#ifdef SIO_TCP_INFO
which might cover MinGW too
Andrew Johnson (anj) wrote : | # |
My MinGW cross-build fails on RHEL-7.6, gcc version 4.9.3 20150626 (Fedora MinGW 4.9.3-1.el7):
../osi/
../osi/
TCP_INFO_v0 tcpInfo;
^
../osi/
if ((status = WSAIoctl(sock, SIO_TCP_INFO, &infoVersion, sizeof(
../osi/
../osi/
return tcpInfo.
../osi/
int status;
^
Freddie Akeroyd (freddie-akeroyd) wrote : | # |
I guess it gets compiled on MinGW as neither macro is defined and 0 >= 0 It may be simplest to use
#if defined(_WIN32) && defined(
mdavidsaver (mdavidsaver) wrote : | # |
Sorry for the vague comment. It was 10 min. before I left for the airport. I think it will be sufficient to pick 5e6226e59597575
Martin Konrad (info-martin-konrad) wrote : | # |
Thanks Michael for the hint, I added this commit to my branch.
Martin Konrad (info-martin-konrad) wrote : | # |
I need some help with AppVeyor. My builds keep failing due to some CI issue: https:/
mdavidsaver (mdavidsaver) wrote : | # |
Have you somehow changed the default image? It seems to be 2019, however the assumed default is 2015 (the default default).
Martin Konrad (info-martin-konrad) wrote : | # |
AppVeyor build succeeded: https:/
mdavidsaver (mdavidsaver) wrote : | # |
That's enough for me.
Preview Diff
1 | diff --git a/src/ioc/misc/dbCore.dbd b/src/ioc/misc/dbCore.dbd |
2 | index 9d5ae94..898bb59 100644 |
3 | --- a/src/ioc/misc/dbCore.dbd |
4 | +++ b/src/ioc/misc/dbCore.dbd |
5 | @@ -25,3 +25,6 @@ variable(callbackParallelThreadsDefault,int) |
6 | |
7 | # Real-time operation |
8 | variable(dbThreadRealtimeLock,int) |
9 | + |
10 | +# show logClient network activity |
11 | +variable(logClientDebug,int) |
12 | diff --git a/src/libCom/log/iocLog.c b/src/libCom/log/iocLog.c |
13 | index e62da20..ba78041 100644 |
14 | --- a/src/libCom/log/iocLog.c |
15 | +++ b/src/libCom/log/iocLog.c |
16 | @@ -18,8 +18,10 @@ |
17 | |
18 | #define epicsExportSharedSymbols |
19 | #include "envDefs.h" |
20 | +#include "errlog.h" |
21 | #include "logClient.h" |
22 | #include "iocLog.h" |
23 | +#include "epicsExit.h" |
24 | |
25 | int iocLogDisable = 0; |
26 | |
27 | @@ -75,6 +77,24 @@ void epicsShareAPI epicsShareAPI iocLogFlush (void) |
28 | } |
29 | |
30 | /* |
31 | + * logClientSendMessage () |
32 | + */ |
33 | +static void logClientSendMessage ( logClientId id, const char * message ) |
34 | +{ |
35 | + if ( !iocLogDisable ) { |
36 | + logClientSend (id, message); |
37 | + } |
38 | +} |
39 | + |
40 | +/* |
41 | + * iocLogClientDestroy() |
42 | + */ |
43 | +static void iocLogClientDestroy (logClientId id) |
44 | +{ |
45 | + errlogRemoveListeners (logClientSendMessage, id); |
46 | +} |
47 | + |
48 | +/* |
49 | * iocLogClientInit() |
50 | */ |
51 | static logClientId iocLogClientInit (void) |
52 | @@ -89,6 +109,10 @@ static logClientId iocLogClientInit (void) |
53 | return NULL; |
54 | } |
55 | id = logClientCreate (addr, port); |
56 | + if (id != NULL) { |
57 | + errlogAddListener (logClientSendMessage, id); |
58 | + epicsAtExit (iocLogClientDestroy, id); |
59 | + } |
60 | return id; |
61 | } |
62 | |
63 | @@ -135,3 +159,4 @@ logClientId epicsShareAPI logClientInit (void) |
64 | { |
65 | return iocLogClientInit (); |
66 | } |
67 | + |
68 | diff --git a/src/libCom/log/logClient.c b/src/libCom/log/logClient.c |
69 | index 99ee671..9a09ef7 100644 |
70 | --- a/src/libCom/log/logClient.c |
71 | +++ b/src/libCom/log/logClient.c |
72 | @@ -21,11 +21,11 @@ |
73 | #include <string.h> |
74 | #include <stdio.h> |
75 | |
76 | +#define EPICS_PRIVATE_API |
77 | #define epicsExportSharedSymbols |
78 | #include "dbDefs.h" |
79 | #include "epicsEvent.h" |
80 | #include "iocLog.h" |
81 | -#include "errlog.h" |
82 | #include "epicsMutex.h" |
83 | #include "epicsThread.h" |
84 | #include "epicsTime.h" |
85 | @@ -33,9 +33,13 @@ |
86 | #include "epicsAssert.h" |
87 | #include "epicsExit.h" |
88 | #include "epicsSignal.h" |
89 | +#include "epicsExport.h" |
90 | |
91 | #include "logClient.h" |
92 | |
93 | +int logClientDebug = 0; |
94 | +epicsExportAddress (int, logClientDebug); |
95 | + |
96 | typedef struct { |
97 | char msgBuf[0x4000]; |
98 | struct sockaddr_in addr; |
99 | @@ -44,8 +48,10 @@ typedef struct { |
100 | SOCKET sock; |
101 | epicsThreadId restartThreadId; |
102 | epicsEventId stateChangeNotify; |
103 | + epicsEventId shutdownNotify; |
104 | unsigned connectCount; |
105 | unsigned nextMsgIndex; |
106 | + unsigned backlog; |
107 | unsigned connected; |
108 | unsigned shutdown; |
109 | unsigned shutdownConfirm; |
110 | @@ -53,7 +59,6 @@ typedef struct { |
111 | } logClient; |
112 | |
113 | static const double LOG_RESTART_DELAY = 5.0; /* sec */ |
114 | -static const double LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT = 5.0; /* sec */ |
115 | static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0; /* sec */ |
116 | |
117 | /* |
118 | @@ -66,10 +71,10 @@ static char* logClientPrefix = NULL; |
119 | */ |
120 | static void logClientClose ( logClient *pClient ) |
121 | { |
122 | -# ifdef DEBUG |
123 | + if (logClientDebug) { |
124 | fprintf (stderr, "log client: lingering for connection close..."); |
125 | fflush (stderr); |
126 | -# endif |
127 | + } |
128 | |
129 | /* |
130 | * mutex on |
131 | @@ -84,8 +89,6 @@ static void logClientClose ( logClient *pClient ) |
132 | pClient->sock = INVALID_SOCKET; |
133 | } |
134 | |
135 | - pClient->nextMsgIndex = 0u; |
136 | - memset ( pClient->msgBuf, '\0', sizeof ( pClient->msgBuf ) ); |
137 | pClient->connected = 0u; |
138 | |
139 | /* |
140 | @@ -93,9 +96,8 @@ static void logClientClose ( logClient *pClient ) |
141 | */ |
142 | epicsMutexUnlock (pClient->mutex); |
143 | |
144 | -# ifdef DEBUG |
145 | + if (logClientDebug) |
146 | fprintf (stderr, "done\n"); |
147 | -# endif |
148 | } |
149 | |
150 | /* |
151 | @@ -113,6 +115,7 @@ static void logClientDestroy (logClientId id) |
152 | epicsMutexMustLock ( pClient->mutex ); |
153 | pClient->shutdown = 1u; |
154 | epicsMutexUnlock ( pClient->mutex ); |
155 | + epicsEventSignal ( pClient->shutdownNotify ); |
156 | |
157 | /* unblock log client thread blocking in send() or connect() */ |
158 | interruptInfo = |
159 | @@ -154,13 +157,11 @@ static void logClientDestroy (logClientId id) |
160 | return; |
161 | } |
162 | |
163 | - errlogRemoveListeners ( logClientSendMessage, (void *) pClient ); |
164 | - |
165 | logClientClose ( pClient ); |
166 | |
167 | epicsMutexDestroy ( pClient->mutex ); |
168 | - |
169 | epicsEventDestroy ( pClient->stateChangeNotify ); |
170 | + epicsEventDestroy ( pClient->shutdownNotify ); |
171 | |
172 | free ( pClient ); |
173 | } |
174 | @@ -176,61 +177,26 @@ static void sendMessageChunk(logClient * pClient, const char * message) { |
175 | unsigned msgBufBytesLeft = |
176 | sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex; |
177 | |
178 | - if ( strSize > msgBufBytesLeft ) { |
179 | - int status; |
180 | - |
181 | - if ( ! pClient->connected ) { |
182 | - break; |
183 | - } |
184 | - |
185 | - if ( msgBufBytesLeft > 0u ) { |
186 | - memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], |
187 | - message, msgBufBytesLeft ); |
188 | - pClient->nextMsgIndex += msgBufBytesLeft; |
189 | - strSize -= msgBufBytesLeft; |
190 | - message += msgBufBytesLeft; |
191 | - } |
192 | - |
193 | - status = send ( pClient->sock, pClient->msgBuf, |
194 | - pClient->nextMsgIndex, 0 ); |
195 | - if ( status > 0 ) { |
196 | - unsigned nSent = (unsigned) status; |
197 | - if ( nSent < pClient->nextMsgIndex ) { |
198 | - unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent; |
199 | - memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], |
200 | - newNextMsgIndex ); |
201 | - pClient->nextMsgIndex = newNextMsgIndex; |
202 | - } |
203 | - else { |
204 | - pClient->nextMsgIndex = 0u; |
205 | - } |
206 | - } |
207 | - else { |
208 | - if ( ! pClient->shutdown ) { |
209 | - char sockErrBuf[64]; |
210 | - if ( status ) { |
211 | - epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); |
212 | - } |
213 | - else { |
214 | - strcpy ( sockErrBuf, "server initiated disconnect" ); |
215 | - } |
216 | - fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n", |
217 | - pClient->name, sockErrBuf ); |
218 | - } |
219 | - logClientClose ( pClient ); |
220 | - break; |
221 | - } |
222 | + if ( msgBufBytesLeft < strSize && pClient->nextMsgIndex != 0u && pClient->connected) |
223 | + { |
224 | + /* buffer is full, thus flush it */ |
225 | + logClientFlush ( pClient ); |
226 | + msgBufBytesLeft = sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex; |
227 | } |
228 | - else { |
229 | - memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], |
230 | - message, strSize ); |
231 | - pClient->nextMsgIndex += strSize; |
232 | + if ( msgBufBytesLeft == 0u ) { |
233 | + fprintf ( stderr, "log client: messages to \"%s\" are lost\n", |
234 | + pClient->name ); |
235 | break; |
236 | } |
237 | + if ( msgBufBytesLeft > strSize) msgBufBytesLeft = strSize; |
238 | + memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], |
239 | + message, msgBufBytesLeft ); |
240 | + pClient->nextMsgIndex += msgBufBytesLeft; |
241 | + strSize -= msgBufBytesLeft; |
242 | + message += msgBufBytesLeft; |
243 | } |
244 | } |
245 | |
246 | - |
247 | /* |
248 | * logClientSend () |
249 | */ |
250 | @@ -255,43 +221,54 @@ void epicsShareAPI logClientSend ( logClientId id, const char * message ) |
251 | |
252 | void epicsShareAPI logClientFlush ( logClientId id ) |
253 | { |
254 | + unsigned nSent; |
255 | + int status = 0; |
256 | + |
257 | logClient * pClient = ( logClient * ) id; |
258 | |
259 | - if ( ! pClient ) { |
260 | + if ( ! pClient || ! pClient->connected ) { |
261 | return; |
262 | } |
263 | |
264 | epicsMutexMustLock ( pClient->mutex ); |
265 | |
266 | - while ( pClient->nextMsgIndex && pClient->connected ) { |
267 | - int status = send ( pClient->sock, pClient->msgBuf, |
268 | - pClient->nextMsgIndex, 0 ); |
269 | - if ( status > 0 ) { |
270 | - unsigned nSent = (unsigned) status; |
271 | - if ( nSent < pClient->nextMsgIndex ) { |
272 | - unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent; |
273 | - memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], |
274 | - newNextMsgIndex ); |
275 | - pClient->nextMsgIndex = newNextMsgIndex; |
276 | - } |
277 | - else { |
278 | - pClient->nextMsgIndex = 0u; |
279 | - } |
280 | + nSent = pClient->backlog; |
281 | + while ( nSent < pClient->nextMsgIndex && pClient->connected ) { |
282 | + status = send ( pClient->sock, pClient->msgBuf + nSent, |
283 | + pClient->nextMsgIndex - nSent, 0 ); |
284 | + if ( status < 0 ) break; |
285 | + nSent += status; |
286 | + } |
287 | + |
288 | + if ( pClient->backlog > 0 && status >= 0 ) |
289 | + { |
290 | + /* On Linux send 0 bytes can detect EPIPE */ |
291 | + /* NOOP on Windows, fails on vxWorks */ |
292 | + errno = 0; |
293 | + status = send ( pClient->sock, NULL, 0, 0 ); |
294 | + if (!(errno == ECONNRESET || errno == EPIPE)) status = 0; |
295 | + } |
296 | + |
297 | + if ( status < 0 ) { |
298 | + if ( ! pClient->shutdown ) { |
299 | + char sockErrBuf[128]; |
300 | + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); |
301 | + fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n", |
302 | + pClient->name, sockErrBuf ); |
303 | } |
304 | - else { |
305 | - if ( ! pClient->shutdown ) { |
306 | - char sockErrBuf[64]; |
307 | - if ( status ) { |
308 | - epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); |
309 | - } |
310 | - else { |
311 | - strcpy ( sockErrBuf, "server initiated disconnect" ); |
312 | - } |
313 | - fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n", |
314 | - pClient->name, sockErrBuf ); |
315 | - } |
316 | - logClientClose ( pClient ); |
317 | - break; |
318 | + pClient->backlog = 0; |
319 | + logClientClose ( pClient ); |
320 | + } |
321 | + else if ( nSent > 0 && pClient->nextMsgIndex > 0 ) { |
322 | + int backlog = epicsSocketUnsentCount ( pClient->sock ); |
323 | + if (backlog >= 0) { |
324 | + pClient->backlog = backlog; |
325 | + nSent -= backlog; |
326 | + } |
327 | + pClient->nextMsgIndex -= nSent; |
328 | + if ( nSent > 0 && pClient->nextMsgIndex > 0 ) { |
329 | + memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], |
330 | + pClient->nextMsgIndex ); |
331 | } |
332 | } |
333 | epicsMutexUnlock ( pClient->mutex ); |
334 | @@ -302,10 +279,10 @@ void epicsShareAPI logClientFlush ( logClientId id ) |
335 | */ |
336 | static void logClientMakeSock (logClient *pClient) |
337 | { |
338 | - |
339 | -# ifdef DEBUG |
340 | + if (logClientDebug) { |
341 | fprintf (stderr, "log client: creating socket..."); |
342 | -# endif |
343 | + fflush (stderr); |
344 | + } |
345 | |
346 | epicsMutexMustLock (pClient->mutex); |
347 | |
348 | @@ -314,7 +291,7 @@ static void logClientMakeSock (logClient *pClient) |
349 | */ |
350 | pClient->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, 0 ); |
351 | if ( pClient->sock == INVALID_SOCKET ) { |
352 | - char sockErrBuf[64]; |
353 | + char sockErrBuf[128]; |
354 | epicsSocketConvertErrnoToString ( |
355 | sockErrBuf, sizeof ( sockErrBuf ) ); |
356 | fprintf ( stderr, "log client: no socket error %s\n", |
357 | @@ -323,10 +300,8 @@ static void logClientMakeSock (logClient *pClient) |
358 | |
359 | epicsMutexUnlock (pClient->mutex); |
360 | |
361 | -# ifdef DEBUG |
362 | + if (logClientDebug) |
363 | fprintf (stderr, "done\n"); |
364 | -# endif |
365 | - |
366 | } |
367 | |
368 | /* |
369 | @@ -366,7 +341,7 @@ static void logClientConnect (logClient *pClient) |
370 | } |
371 | else { |
372 | if ( pClient->connFailStatus != errnoCpy && ! pClient->shutdown ) { |
373 | - char sockErrBuf[64]; |
374 | + char sockErrBuf[128]; |
375 | epicsSocketConvertErrnoToString ( |
376 | sockErrBuf, sizeof ( sockErrBuf ) ); |
377 | fprintf (stderr, |
378 | @@ -392,7 +367,7 @@ static void logClientConnect (logClient *pClient) |
379 | optval = TRUE; |
380 | status = setsockopt (pClient->sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(optval)); |
381 | if (status<0) { |
382 | - char sockErrBuf[64]; |
383 | + char sockErrBuf[128]; |
384 | epicsSocketConvertErrnoToString ( |
385 | sockErrBuf, sizeof ( sockErrBuf ) ); |
386 | fprintf (stderr, "log client: unable to enable keepalive option because \"%s\"\n", sockErrBuf); |
387 | @@ -404,11 +379,11 @@ static void logClientConnect (logClient *pClient) |
388 | */ |
389 | status = shutdown (pClient->sock, SHUT_RD); |
390 | if (status < 0) { |
391 | - char sockErrBuf[64]; |
392 | + char sockErrBuf[128]; |
393 | epicsSocketConvertErrnoToString ( |
394 | sockErrBuf, sizeof ( sockErrBuf ) ); |
395 | - fprintf (stderr, "%s:%d shutdown(%d,SHUT_RD) error was \"%s\"\n", |
396 | - __FILE__, __LINE__, pClient->sock, sockErrBuf); |
397 | + fprintf (stderr, "%s:%d shutdown(sock,SHUT_RD) error was \"%s\"\n", |
398 | + __FILE__, __LINE__, sockErrBuf); |
399 | /* not fatal (although it shouldn't happen) */ |
400 | } |
401 | |
402 | @@ -425,7 +400,7 @@ static void logClientConnect (logClient *pClient) |
403 | lingerval.l_linger = 60*5; |
404 | status = setsockopt (pClient->sock, SOL_SOCKET, SO_LINGER, (char *) &lingerval, sizeof(lingerval)); |
405 | if (status<0) { |
406 | - char sockErrBuf[64]; |
407 | + char sockErrBuf[128]; |
408 | epicsSocketConvertErrnoToString ( |
409 | sockErrBuf, sizeof ( sockErrBuf ) ); |
410 | fprintf (stderr, "log client: unable to set linger options because \"%s\"\n", sockErrBuf); |
411 | @@ -457,14 +432,10 @@ static void logClientRestart ( logClientId id ) |
412 | |
413 | epicsMutexUnlock ( pClient->mutex ); |
414 | |
415 | - if ( isConn ) { |
416 | - logClientFlush ( pClient ); |
417 | - } |
418 | - else { |
419 | - logClientConnect ( pClient ); |
420 | - } |
421 | - |
422 | - epicsThreadSleep ( LOG_RESTART_DELAY ); |
423 | + if ( ! isConn ) logClientConnect ( pClient ); |
424 | + logClientFlush ( pClient ); |
425 | + |
426 | + epicsEventWaitWithTimeout ( pClient->shutdownNotify, LOG_RESTART_DELAY); |
427 | |
428 | epicsMutexMustLock ( pClient->mutex ); |
429 | } |
430 | @@ -480,9 +451,7 @@ static void logClientRestart ( logClientId id ) |
431 | logClientId epicsShareAPI logClientCreate ( |
432 | struct in_addr server_addr, unsigned short server_port) |
433 | { |
434 | - epicsTimeStamp begin, current; |
435 | logClient *pClient; |
436 | - double diff; |
437 | |
438 | pClient = calloc (1, sizeof (*pClient)); |
439 | if (pClient==NULL) { |
440 | @@ -507,14 +476,22 @@ logClientId epicsShareAPI logClientCreate ( |
441 | pClient->shutdownConfirm = 0; |
442 | |
443 | epicsAtExit (logClientDestroy, (void*) pClient); |
444 | - |
445 | + |
446 | pClient->stateChangeNotify = epicsEventCreate (epicsEventEmpty); |
447 | if ( ! pClient->stateChangeNotify ) { |
448 | epicsMutexDestroy ( pClient->mutex ); |
449 | free ( pClient ); |
450 | return NULL; |
451 | } |
452 | - |
453 | + |
454 | + pClient->shutdownNotify = epicsEventCreate (epicsEventEmpty); |
455 | + if ( ! pClient->shutdownNotify ) { |
456 | + epicsMutexDestroy ( pClient->mutex ); |
457 | + epicsEventDestroy ( pClient->stateChangeNotify ); |
458 | + free ( pClient ); |
459 | + return NULL; |
460 | + } |
461 | + |
462 | pClient->restartThreadId = epicsThreadCreate ( |
463 | "logRestart", epicsThreadPriorityLow, |
464 | epicsThreadGetStackSize(epicsThreadStackSmall), |
465 | @@ -522,35 +499,12 @@ logClientId epicsShareAPI logClientCreate ( |
466 | if ( pClient->restartThreadId == NULL ) { |
467 | epicsMutexDestroy ( pClient->mutex ); |
468 | epicsEventDestroy ( pClient->stateChangeNotify ); |
469 | + epicsEventDestroy ( pClient->shutdownNotify ); |
470 | free (pClient); |
471 | fprintf(stderr, "log client: unable to start log client connection watch dog thread\n"); |
472 | return NULL; |
473 | } |
474 | |
475 | - /* |
476 | - * attempt to synchronize with circuit connect |
477 | - */ |
478 | - epicsTimeGetCurrent ( & begin ); |
479 | - epicsMutexMustLock ( pClient->mutex ); |
480 | - do { |
481 | - epicsMutexUnlock ( pClient->mutex ); |
482 | - epicsEventWaitWithTimeout ( |
483 | - pClient->stateChangeNotify, |
484 | - LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT / 10.0 ); |
485 | - epicsTimeGetCurrent ( & current ); |
486 | - diff = epicsTimeDiffInSeconds ( & current, & begin ); |
487 | - epicsMutexMustLock ( pClient->mutex ); |
488 | - } |
489 | - while ( ! pClient->connected && diff < LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT ); |
490 | - epicsMutexUnlock ( pClient->mutex ); |
491 | - |
492 | - if ( ! pClient->connected ) { |
493 | - fprintf (stderr, "log client create: timed out synchronizing with circuit connect to \"%s\" after %.1f seconds\n", |
494 | - pClient->name, LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT ); |
495 | - } |
496 | - |
497 | - errlogAddListener ( logClientSendMessage, (void *) pClient ); |
498 | - |
499 | return (void *) pClient; |
500 | } |
501 | |
502 | @@ -568,24 +522,21 @@ void epicsShareAPI logClientShow (logClientId id, unsigned level) |
503 | printf ("log client: disconnected from log server at \"%s\"\n", pClient->name); |
504 | } |
505 | |
506 | - if (level>1) { |
507 | - printf ("log client: sock=%s, connect cycles = %u\n", |
508 | - pClient->sock==INVALID_SOCKET?"INVALID":"OK", |
509 | - pClient->connectCount); |
510 | - } |
511 | - |
512 | if (logClientPrefix) { |
513 | printf ("log client: prefix is \"%s\"\n", logClientPrefix); |
514 | } |
515 | -} |
516 | |
517 | -/* |
518 | - * logClientSendMessage (); deprecated |
519 | - */ |
520 | -void logClientSendMessage ( logClientId id, const char * message ) |
521 | -{ |
522 | - if ( !iocLogDisable ) { |
523 | - logClientSend (id, message); |
524 | + if (level>0) { |
525 | + printf ("log client: sock %s, connect cycles = %u\n", |
526 | + pClient->sock==INVALID_SOCKET?"INVALID":"OK", |
527 | + pClient->connectCount); |
528 | + } |
529 | + if (level>1) { |
530 | + printf ("log client: %u bytes in buffer\n", pClient->nextMsgIndex); |
531 | + if (pClient->nextMsgIndex) |
532 | + printf("-------------------------\n" |
533 | + "%.*s-------------------------\n", |
534 | + (int)(pClient->nextMsgIndex), pClient->msgBuf); |
535 | } |
536 | } |
537 | |
538 | diff --git a/src/libCom/log/logClient.h b/src/libCom/log/logClient.h |
539 | index 1797bbb..3b3f63a 100644 |
540 | --- a/src/libCom/log/logClient.h |
541 | +++ b/src/libCom/log/logClient.h |
542 | @@ -38,7 +38,6 @@ epicsShareFunc void epicsShareAPI iocLogPrefix(const char* prefix); |
543 | /* deprecated interface; retained for backward compatibility */ |
544 | /* note: implementations are in iocLog.c, not logClient.c */ |
545 | epicsShareFunc logClientId epicsShareAPI logClientInit (void); |
546 | -epicsShareFunc void logClientSendMessage (logClientId id, const char *message); |
547 | |
548 | #ifdef __cplusplus |
549 | } |
550 | diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile |
551 | index e05aec3..00685d8 100644 |
552 | --- a/src/libCom/osi/Makefile |
553 | +++ b/src/libCom/osi/Makefile |
554 | @@ -86,6 +86,7 @@ endif |
555 | |
556 | Com_SRCS += osdSock.c |
557 | Com_SRCS += osdSockAddrReuse.cpp |
558 | +Com_SRCS += osdSockUnsentCount.c |
559 | Com_SRCS += osiSock.c |
560 | Com_SRCS += systemCallIntMech.cpp |
561 | Com_SRCS += epicsSocketConvertErrnoToString.cpp |
562 | diff --git a/src/libCom/osi/os/Darwin/osdSockUnsentCount.c b/src/libCom/osi/os/Darwin/osdSockUnsentCount.c |
563 | new file mode 100644 |
564 | index 0000000..20bd82b |
565 | --- /dev/null |
566 | +++ b/src/libCom/osi/os/Darwin/osdSockUnsentCount.c |
567 | @@ -0,0 +1,19 @@ |
568 | +/*************************************************************************\ |
569 | +* EPICS BASE is distributed subject to a Software License Agreement found |
570 | +* in file LICENSE that is included with this distribution. |
571 | +\*************************************************************************/ |
572 | + |
573 | +#define EPICS_PRIVATE_API |
574 | +#include "osiSock.h" |
575 | + |
576 | +/* |
577 | + * epicsSocketUnsentCount () |
578 | + * See https://www.unix.com/man-page/osx/2/setsockopt |
579 | + */ |
580 | +int epicsSocketUnsentCount(SOCKET sock) { |
581 | + int unsent; |
582 | + socklen_t len = sizeof(unsent); |
583 | + if (getsockopt(sock, SOL_SOCKET, SO_NWRITE, &unsent, &len) == 0) |
584 | + return unsent; |
585 | + return -1; |
586 | +} |
587 | diff --git a/src/libCom/osi/os/Linux/osdSockUnsentCount.c b/src/libCom/osi/os/Linux/osdSockUnsentCount.c |
588 | new file mode 100644 |
589 | index 0000000..3c0a8f9 |
590 | --- /dev/null |
591 | +++ b/src/libCom/osi/os/Linux/osdSockUnsentCount.c |
592 | @@ -0,0 +1,19 @@ |
593 | +/*************************************************************************\ |
594 | +* EPICS BASE is distributed subject to a Software License Agreement found |
595 | +* in file LICENSE that is included with this distribution. |
596 | +\*************************************************************************/ |
597 | + |
598 | +#include <linux/sockios.h> |
599 | +#define EPICS_PRIVATE_API |
600 | +#include "osiSock.h" |
601 | + |
602 | +/* |
603 | + * epicsSocketUnsentCount () |
604 | + * See https://linux.die.net/man/7/tcp |
605 | + */ |
606 | +int epicsSocketUnsentCount(SOCKET sock) { |
607 | + int unsent; |
608 | + if (ioctl(sock, SIOCOUTQ, &unsent) == 0) |
609 | + return unsent; |
610 | + return -1; |
611 | +} |
612 | diff --git a/src/libCom/osi/os/WIN32/osdSockUnsentCount.c b/src/libCom/osi/os/WIN32/osdSockUnsentCount.c |
613 | new file mode 100644 |
614 | index 0000000..3f4ab3e |
615 | --- /dev/null |
616 | +++ b/src/libCom/osi/os/WIN32/osdSockUnsentCount.c |
617 | @@ -0,0 +1,26 @@ |
618 | +/*************************************************************************\ |
619 | +* EPICS BASE is distributed subject to a Software License Agreement found |
620 | +* in file LICENSE that is included with this distribution. |
621 | +\*************************************************************************/ |
622 | + |
623 | +#define epicsExportSharedSymbols |
624 | +#define EPICS_PRIVATE_API |
625 | +#include "osiSock.h" |
626 | +#include <mstcpip.h> |
627 | + |
628 | +/* |
629 | + * epicsSocketUnsentCount () |
630 | + * See https://docs.microsoft.com/en-us/windows/win32/api/mstcpip/ns-mstcpip-tcp_info_v0 |
631 | + */ |
632 | +int epicsSocketUnsentCount(SOCKET sock) { |
633 | +#ifdef SIO_TCP_INFO |
634 | +/* Windows 10 Version 1703 / Server 2016 */ |
635 | + DWORD infoVersion = 0, bytesReturned; |
636 | + TCP_INFO_v0 tcpInfo; |
637 | + int status; |
638 | + if ((status = WSAIoctl(sock, SIO_TCP_INFO, &infoVersion, sizeof(infoVersion), |
639 | + &tcpInfo, sizeof(tcpInfo), &bytesReturned, NULL, NULL)) == 0) |
640 | + return tcpInfo.BytesInFlight; |
641 | +#endif |
642 | + return -1; |
643 | +} |
644 | diff --git a/src/libCom/osi/os/default/osdSockUnsentCount.c b/src/libCom/osi/os/default/osdSockUnsentCount.c |
645 | new file mode 100644 |
646 | index 0000000..ef01e9b |
647 | --- /dev/null |
648 | +++ b/src/libCom/osi/os/default/osdSockUnsentCount.c |
649 | @@ -0,0 +1,15 @@ |
650 | +/*************************************************************************\ |
651 | +* EPICS BASE is distributed subject to a Software License Agreement found |
652 | +* in file LICENSE that is included with this distribution. |
653 | +\*************************************************************************/ |
654 | + |
655 | +#define EPICS_PRIVATE_API |
656 | +#include "osiSock.h" |
657 | + |
658 | +/* |
659 | + * epicsSocketUnsentCount () |
660 | + */ |
661 | +int epicsSocketUnsentCount(SOCKET sock) { |
662 | + /* not implemented */ |
663 | + return -1; |
664 | +} |
665 | diff --git a/src/libCom/osi/os/iOS/osdSockUnsentCount.c b/src/libCom/osi/os/iOS/osdSockUnsentCount.c |
666 | new file mode 100644 |
667 | index 0000000..20bd82b |
668 | --- /dev/null |
669 | +++ b/src/libCom/osi/os/iOS/osdSockUnsentCount.c |
670 | @@ -0,0 +1,19 @@ |
671 | +/*************************************************************************\ |
672 | +* EPICS BASE is distributed subject to a Software License Agreement found |
673 | +* in file LICENSE that is included with this distribution. |
674 | +\*************************************************************************/ |
675 | + |
676 | +#define EPICS_PRIVATE_API |
677 | +#include "osiSock.h" |
678 | + |
679 | +/* |
680 | + * epicsSocketUnsentCount () |
681 | + * See https://www.unix.com/man-page/osx/2/setsockopt |
682 | + */ |
683 | +int epicsSocketUnsentCount(SOCKET sock) { |
684 | + int unsent; |
685 | + socklen_t len = sizeof(unsent); |
686 | + if (getsockopt(sock, SOL_SOCKET, SO_NWRITE, &unsent, &len) == 0) |
687 | + return unsent; |
688 | + return -1; |
689 | +} |
690 | diff --git a/src/libCom/osi/osiSock.h b/src/libCom/osi/osiSock.h |
691 | index 061619e..6e3b053 100644 |
692 | --- a/src/libCom/osi/osiSock.h |
693 | +++ b/src/libCom/osi/osiSock.h |
694 | @@ -52,6 +52,14 @@ enum epicsSocketSystemCallInterruptMechanismQueryInfo { |
695 | epicsShareFunc enum epicsSocketSystemCallInterruptMechanismQueryInfo |
696 | epicsSocketSystemCallInterruptMechanismQuery (); |
697 | |
698 | +#ifdef EPICS_PRIVATE_API |
699 | +/* |
700 | + * Some systems (e.g Linux and Windows 10) allow to check the amount |
701 | + * of unsent data in the output queue. |
702 | + * Returns -1 if the information is not available. |
703 | + */ |
704 | +epicsShareFunc int epicsSocketUnsentCount(SOCKET sock); |
705 | +#endif |
706 | |
707 | /* |
708 | * convert socket address to ASCII in this order |
Backport of https:/ /code.launchpad .net/~dirk. zimoch/ epics-base/ +git/epics- base/+merge/ 372925