Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25a6340993 | ||
|
|
a3652fd54e | ||
|
|
107ae2cee8 | ||
|
|
deb5e9c973 | ||
|
|
196f2302a4 | ||
|
|
2a21b01b0e | ||
|
|
56465da07f | ||
|
|
ee9457970a | ||
|
|
89a3746869 | ||
|
|
5be8f4999d | ||
|
|
b278c803ce | ||
|
|
50b8361078 | ||
|
|
2a121a4276 | ||
|
|
7b03ab0182 | ||
|
|
73a224a6ce |
@@ -1,4 +1,5 @@
|
||||
/************************************************************************/
|
||||
/* $Id$ */
|
||||
/* */
|
||||
/* L O S A L A M O S */
|
||||
/* Los Alamos National Laboratory */
|
||||
@@ -45,6 +46,7 @@
|
||||
/* 021794 joh turn on SO_REUSEADDR only after the test for */
|
||||
/* address in use so that test works on UNIX */
|
||||
/* kernels that support multicast */
|
||||
/* $Log$ */
|
||||
/* */
|
||||
/*_begin */
|
||||
/************************************************************************/
|
||||
@@ -1044,6 +1046,16 @@ LOCAL void udp_recv_msg(struct ioc_in_use *piiu)
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
# ifdef linux
|
||||
/*
|
||||
* Avoid spurious ECONNREFUSED bug
|
||||
* in linux
|
||||
*/
|
||||
if (MYERRNO==ECONNREFUSED) {
|
||||
UNLOCK;
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
ca_printf("Unexpected UDP failure %s\n", strerror(MYERRNO));
|
||||
}
|
||||
else if(status > 0){
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* REPEATER.C
|
||||
*
|
||||
* CA broadcast repeater
|
||||
@@ -59,6 +61,8 @@
|
||||
* .08 102993 joh toggle set sock opt to set
|
||||
* .09 070195 joh discover client has vanished by connecting its
|
||||
* datagram socket (and watching for ECONNREFUSED)
|
||||
*
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
static char *sccsId = "@(#)$Id$";
|
||||
@@ -149,6 +153,15 @@ void ca_repeater()
|
||||
&from_size);
|
||||
|
||||
if(size < 0){
|
||||
# ifdef linux
|
||||
/*
|
||||
* Avoid spurious ECONNREFUSED bug
|
||||
* in linux
|
||||
*/
|
||||
if (MYERRNO==ECONNREFUSED) {
|
||||
continue;
|
||||
}
|
||||
# endif
|
||||
ca_printf("CA Repeater: recv err %s\n",
|
||||
strerror(MYERRNO));
|
||||
continue;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
@@ -26,17 +27,18 @@
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Lawrence Berkley National Laboratory
|
||||
* Lawrence Berkley National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Windows includes
|
||||
*/
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "iocinf.h"
|
||||
|
||||
@@ -44,6 +46,10 @@
|
||||
#error This source is specific to WIN32
|
||||
#endif
|
||||
|
||||
long offset_time; /* time diff (sec) between 1970 and when windows started */
|
||||
DWORD prev_time;
|
||||
|
||||
static void init_timers();
|
||||
static int get_subnet_mask ( char SubNetMaskStr[256]);
|
||||
static int RegTcpParams (char IpAddr[256], char SubNetMask[256]);
|
||||
static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
|
||||
@@ -55,11 +61,25 @@ static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
|
||||
*/
|
||||
void cac_gettimeval(struct timeval *pt)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
/**
|
||||
The multi-media timers used here should be good to a millisecond
|
||||
resolution. However, since the timer rolls back to 0 every 49.7
|
||||
days (2^32 ms, 4,294,967.296 sec), it's not very good for
|
||||
time stamping over long periods (if Windows is restarted more
|
||||
often than 49 days, it wont be a problem). An attempt is made
|
||||
to keep the time returned increasing, but there is no guarantee
|
||||
the UTC time is right after 49 days.
|
||||
**/
|
||||
|
||||
GetSystemTime(&st);
|
||||
pt->tv_sec = time(NULL);
|
||||
pt->tv_usec = st.wMilliseconds*1000;
|
||||
DWORD win_sys_time; /* time (ms) since windows started */
|
||||
|
||||
win_sys_time = timeGetTime();
|
||||
if (prev_time > win_sys_time) { /* must have been a timer roll-over */
|
||||
offset_time += 4294967; /* add number of seconds in 49.7 days */
|
||||
}
|
||||
pt->tv_sec = (long)win_sys_time/1000 + offset_time; /* time (sec) since 1970 */
|
||||
pt->tv_usec = (long)((win_sys_time % 1000) * 1000);
|
||||
prev_time = win_sys_time;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,8 +122,7 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV)
|
||||
*/
|
||||
int cac_os_depen_init(struct ca_static *pcas)
|
||||
{
|
||||
int status;
|
||||
WSADATA WsaData;
|
||||
int status;
|
||||
|
||||
ca_static = pcas;
|
||||
|
||||
@@ -117,10 +136,7 @@ int cac_os_depen_init(struct ca_static *pcas)
|
||||
|
||||
/* signal(SIGPIPE,SIG_IGN); */
|
||||
|
||||
# ifdef _WINSOCKAPI_
|
||||
status = WSAStartup(MAKEWORD(1,1), &WsaData);
|
||||
assert (status==0);
|
||||
# endif
|
||||
/* DllMain does most OS dependent init & cleanup */
|
||||
|
||||
status = ca_os_independent_init ();
|
||||
|
||||
@@ -414,7 +430,6 @@ static int RegKeyData (CHAR *RegPath, HANDLE hKeyRoot, LPSTR lpzValueName,
|
||||
|
||||
|
||||
retCode = RegQueryValueEx (hKey, // Key handle returned from
|
||||
RegOpenKeyEx.
|
||||
lpzValueName, // Name of value.
|
||||
NULL, // Reserved, dword = NULL.
|
||||
lpdwType, // Type of data.
|
||||
@@ -435,37 +450,56 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
int status;
|
||||
WSADATA WsaData;
|
||||
TIMECAPS tc;
|
||||
UINT wTimerRes;
|
||||
|
||||
switch (dwReason) {
|
||||
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
if ((status = WSAStartup(MAKEWORD(1,1), &WsaData)) != 0)
|
||||
return FALSE;
|
||||
#if _DEBUG
|
||||
|
||||
#if _DEBUG /* for gui applications, setup console for error messages */
|
||||
if (AllocConsole()) {
|
||||
SetConsoleTitle("Channel Access Status");
|
||||
freopen( "CONOUT$", "a", stderr );
|
||||
fprintf(stderr, "Process attached to ca.dll R12\n");
|
||||
}
|
||||
#endif
|
||||
fprintf(stderr, "Process attached to ca.dll R3.12.1\n");
|
||||
#endif /* init. winsock */
|
||||
if ((status = WSAStartup(MAKEWORD(1,1), &WsaData)) != 0) {
|
||||
fprintf(stderr,"Cant init winsock \n");
|
||||
return FALSE;
|
||||
}
|
||||
/* setup multi-media timer */
|
||||
if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
||||
fprintf(stderr,"cant get timer info \n");
|
||||
return FALSE;
|
||||
}
|
||||
/* set for 1 ms resoulution */
|
||||
wTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax);
|
||||
status = timeBeginPeriod(wTimerRes);
|
||||
if (status != TIMERR_NOERROR)
|
||||
fprintf(stderr,"timer setup failed\n");
|
||||
offset_time = (long)time(NULL) - (long)timeGetTime()/1000;
|
||||
prev_time = timeGetTime();
|
||||
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
||||
timeEndPeriod(wTimerRes);
|
||||
|
||||
if ((status = WSACleanup()) !=0)
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Thread attached to ca.dll R12\n");
|
||||
fprintf(stderr, "Thread attached to ca.dll R3.12.1\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
#if _DEBUG
|
||||
fprintf(stderr, "Thread detached from ca.dll R12\n");
|
||||
fprintf(stderr, "Thread detached from ca.dll R3.12.1\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -475,6 +509,8 @@ BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
11
src/libCom/env/envSubr.c
vendored
11
src/libCom/env/envSubr.c
vendored
@@ -32,6 +32,8 @@
|
||||
* vars under vxWorks
|
||||
* .05 04-20-95 anj changes to use CONFIG_ENV
|
||||
* .06 05-24-95 joh added return stmnt to epicsPrtEnvParams()
|
||||
* .07 11-03-96 joh fixed bug occuring when diagnostic is
|
||||
* printed and the env var cant be found
|
||||
*
|
||||
* make options
|
||||
* -DvxWorks makes a version for VxWorks
|
||||
@@ -195,8 +197,9 @@ double *pDouble; /* O pointer to place to store value */
|
||||
if (count == 1) {
|
||||
return 0;
|
||||
}
|
||||
(void)printf("Unable to find a real number in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -250,8 +253,9 @@ struct in_addr *pAddr; /* O pointer to struct to receive inet addr */
|
||||
pAddr->s_addr = status;
|
||||
return 0;
|
||||
}
|
||||
(void)printf("Unable to find an IP address in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -303,8 +307,9 @@ long *pLong; /* O pointer to place to store value */
|
||||
count = sscanf(text, "%ld", pLong);
|
||||
if (count == 1)
|
||||
return 0;
|
||||
(void)printf("Unable to find an integer in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
* vars under vxWorks
|
||||
* .05 04-20-95 anj changes to use CONFIG_ENV
|
||||
* .06 05-24-95 joh added return stmnt to epicsPrtEnvParams()
|
||||
* .07 11-03-96 joh fixed bug occuring when diagnostic is
|
||||
* printed and the env var cant be found
|
||||
*
|
||||
* make options
|
||||
* -DvxWorks makes a version for VxWorks
|
||||
@@ -195,8 +197,9 @@ double *pDouble; /* O pointer to place to store value */
|
||||
if (count == 1) {
|
||||
return 0;
|
||||
}
|
||||
(void)printf("Unable to find a real number in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -250,8 +253,9 @@ struct in_addr *pAddr; /* O pointer to struct to receive inet addr */
|
||||
pAddr->s_addr = status;
|
||||
return 0;
|
||||
}
|
||||
(void)printf("Unable to find an IP address in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -303,8 +307,9 @@ long *pLong; /* O pointer to place to store value */
|
||||
count = sscanf(text, "%ld", pLong);
|
||||
if (count == 1)
|
||||
return 0;
|
||||
(void)printf("Unable to find an integer in %s=%s\n",
|
||||
pParam->name, text);
|
||||
}
|
||||
(void)printf("illegal value for %s:%s\n", pParam->name, text);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
* Modification Log: errPrintfVX.c
|
||||
* -----------------
|
||||
* .01 02-16-95 mrk Extracted from errSymLib.c
|
||||
* $Log$
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
@@ -59,8 +60,6 @@
|
||||
static int mprintf (const char *pFormat, ...);
|
||||
static int vmprintf (const char *pFormat, va_list pvar);
|
||||
|
||||
extern FILE *iocLogFile;
|
||||
|
||||
LOCAL SEM_ID clientWaitForTask;
|
||||
LOCAL SEM_ID clientWaitForCompletion;
|
||||
LOCAL SEM_ID serverWaitForWork;
|
||||
@@ -263,8 +262,7 @@ LOCAL int vmprintf (const char *pFormat, va_list pvar)
|
||||
|
||||
s0 = vfprintf(stdout,pFormat,pvar);
|
||||
fflush(stdout);
|
||||
s1 = vfprintf(iocLogFile,pFormat,pvar);
|
||||
fflush(iocLogFile);
|
||||
s1 = iocLogVPrintf(pFormat,pvar);
|
||||
va_end(pvar);
|
||||
if (s1<0) {
|
||||
return s1;
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
* routines in a backwards compatible way so that
|
||||
* we eliminate delete ambiguity (chance of the same
|
||||
* being reused).
|
||||
* $Log$
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* $Id$
|
||||
* archive logMsg() from several IOC's to a common rotating file
|
||||
*
|
||||
*
|
||||
* Author: Jeffrey O. Hill
|
||||
@@ -33,64 +32,114 @@
|
||||
* .00 joh 080791 Created
|
||||
* .01 joh 081591 Added epics env config
|
||||
* .02 joh 011995 Allow stdio also
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vxWorks.h>
|
||||
#include <ioLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <socket.h>
|
||||
#include <in.h>
|
||||
|
||||
#include <inetLib.h>
|
||||
#include <errnoLib.h>
|
||||
#include <ioLib.h>
|
||||
#include <taskLib.h>
|
||||
#include <logLib.h>
|
||||
#include <inetLib.h>
|
||||
#include <sockLib.h>
|
||||
#include <sysLib.h>
|
||||
#include <semLib.h>
|
||||
#include <rebootLib.h>
|
||||
|
||||
|
||||
#include <epicsPrint.h>
|
||||
#include <envDefs.h>
|
||||
#include <task_params.h>
|
||||
|
||||
LOCAL FILE *iocLogFile = NULL;
|
||||
LOCAL int iocLogFD = ERROR;
|
||||
LOCAL int iocLogDisable = 0;
|
||||
LOCAL unsigned iocLogTries = 0U;
|
||||
LOCAL unsigned iocLogConnectCount = 0U;
|
||||
|
||||
FILE *iocLogFile = NULL;
|
||||
int iocLogFD = ERROR;
|
||||
int iocLogDisable;
|
||||
LOCAL long ioc_log_port;
|
||||
LOCAL struct in_addr ioc_log_addr;
|
||||
|
||||
static long ioc_log_port;
|
||||
static struct in_addr ioc_log_addr;
|
||||
int iocLogInit(void);
|
||||
LOCAL int getConfig(void);
|
||||
LOCAL void failureNotify(ENV_PARAM *pparam);
|
||||
LOCAL void logClientShutdown(void);
|
||||
LOCAL void logRestart(void);
|
||||
LOCAL int iocLogAttach(void);
|
||||
LOCAL void logClientRollLocalPort(void);
|
||||
|
||||
int iocLogInit();
|
||||
static int getConfig();
|
||||
static void failureNoptify();
|
||||
LOCAL SEM_ID iocLogMutex; /* protects stdio */
|
||||
LOCAL SEM_ID iocLogSignal; /* reattach to log server */
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* iocLogInit()
|
||||
*
|
||||
*
|
||||
*/
|
||||
int
|
||||
iocLogInit()
|
||||
int iocLogInit(void)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
int status;
|
||||
int status;
|
||||
int attachStatus;
|
||||
int options;
|
||||
|
||||
if(iocLogDisable){
|
||||
return OK;
|
||||
}
|
||||
|
||||
options = SEM_Q_PRIORITY|SEM_DELETE_SAFE|SEM_INVERSION_SAFE;
|
||||
iocLogMutex = semMCreate(options);
|
||||
if(!iocLogMutex){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
iocLogSignal = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
if(!iocLogSignal){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
attachStatus = iocLogAttach();
|
||||
|
||||
status = rebootHookAdd((FUNCPTR)logClientShutdown);
|
||||
if (status<0) {
|
||||
epicsPrintf("Unable to add log server reboot hook\n");
|
||||
}
|
||||
|
||||
status = taskSpawn(
|
||||
LOG_RESTART_NAME,
|
||||
LOG_RESTART_PRI,
|
||||
LOG_RESTART_OPT,
|
||||
LOG_RESTART_STACK,
|
||||
(FUNCPTR)logRestart,
|
||||
0,0,0,0,0,0,0,0,0,0);
|
||||
if (status<0) {
|
||||
epicsPrintf("Unable to start log server connection watch dog\n");
|
||||
}
|
||||
|
||||
return attachStatus;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* iocLogAttach()
|
||||
*/
|
||||
int iocLogAttach(void)
|
||||
{
|
||||
|
||||
int sock;
|
||||
struct sockaddr_in addr;
|
||||
int status;
|
||||
int optval;
|
||||
FILE *fp;
|
||||
|
||||
status = getConfig();
|
||||
if(status<0){
|
||||
logMsg (
|
||||
"iocLogClient: EPICS environment under specified\n",
|
||||
0,0,0,0,0,0);
|
||||
logMsg (
|
||||
"iocLogClient: failed to initialize\n",
|
||||
0,0,0,0,0,0);
|
||||
epicsPrintf (
|
||||
"iocLogClient: EPICS environment under specified\n");
|
||||
epicsPrintf ("iocLogClient: failed to initialize\n");
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -99,9 +148,8 @@ iocLogInit()
|
||||
SOCK_STREAM, /* type */
|
||||
0); /* deflt proto */
|
||||
if (sock < 0){
|
||||
logMsg( "iocLogClient: no socket errno %d\n",
|
||||
errnoGet(),
|
||||
0,0,0,0,0);
|
||||
epicsPrintf ("iocLogClient: no socket error %s\n",
|
||||
strerror(errno));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -111,7 +159,7 @@ iocLogInit()
|
||||
/* set the port */
|
||||
addr.sin_port = htons(ioc_log_port);
|
||||
|
||||
/* set the port */
|
||||
/* set the addr */
|
||||
addr.sin_addr.s_addr = ioc_log_addr.s_addr;
|
||||
|
||||
/* connect */
|
||||
@@ -123,25 +171,213 @@ iocLogInit()
|
||||
char name[INET_ADDR_LEN];
|
||||
|
||||
inet_ntoa_b(addr.sin_addr, name);
|
||||
logMsg(
|
||||
if (iocLogTries==0U) {
|
||||
epicsPrintf(
|
||||
"iocLogClient: unable to connect to %s port %d because \"%s\"\n",
|
||||
(int) name,
|
||||
addr.sin_port,
|
||||
(int) strerror(errnoGet()),
|
||||
0,0,0);
|
||||
name,
|
||||
addr.sin_port,
|
||||
strerror(errno));
|
||||
}
|
||||
iocLogTries++;
|
||||
close(sock);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
logFdAdd (sock);
|
||||
iocLogTries=0U;
|
||||
iocLogConnectCount++;
|
||||
|
||||
iocLogFile = fdopen (sock, "a");
|
||||
/*
|
||||
* discover that the connection has expired
|
||||
* (after a long delay)
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = setsockopt( sock,
|
||||
SOL_SOCKET,
|
||||
SO_KEEPALIVE,
|
||||
(char *) &optval,
|
||||
sizeof(optval));
|
||||
if(status<0){
|
||||
epicsPrintf ("iocLogClient: %s\n", strerror(errno));
|
||||
close(sock);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* set how long we will wait for the TCP state machine
|
||||
* to clean up when we issue a close(). This
|
||||
* guarantees that messages are serialized when we
|
||||
* switch connections.
|
||||
*/
|
||||
{
|
||||
struct linger lingerval;
|
||||
|
||||
lingerval.l_onoff = TRUE;
|
||||
lingerval.l_linger = 60*5;
|
||||
status = setsockopt( sock,
|
||||
SOL_SOCKET,
|
||||
SO_LINGER,
|
||||
(char *) &lingerval,
|
||||
sizeof(lingerval));
|
||||
if(status<0){
|
||||
epicsPrintf ("iocLogClient: %s\n", strerror(errno));
|
||||
close(sock);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
fp = fdopen (sock, "a");
|
||||
|
||||
/*
|
||||
* mutex on
|
||||
*/
|
||||
status = semTake(iocLogMutex, WAIT_FOREVER);
|
||||
assert(status==OK);
|
||||
|
||||
/*
|
||||
* close any preexisting connection to the log server
|
||||
*/
|
||||
if (iocLogFile) {
|
||||
logFdDelete(iocLogFD);
|
||||
fclose(iocLogFile);
|
||||
iocLogFile = NULL;
|
||||
iocLogFD = ERROR;
|
||||
}
|
||||
else if (iocLogFD!=ERROR) {
|
||||
logFdDelete(iocLogFD);
|
||||
close(iocLogFD);
|
||||
iocLogFD = ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* export the new connection
|
||||
*/
|
||||
iocLogFD = sock;
|
||||
logFdAdd (iocLogFD);
|
||||
iocLogFile = fp;
|
||||
|
||||
/*
|
||||
* mutex off
|
||||
*/
|
||||
status = semGive(iocLogMutex);
|
||||
assert(status==OK);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* logRestart()
|
||||
*/
|
||||
LOCAL void logRestart(void)
|
||||
{
|
||||
int status;
|
||||
int reattach;
|
||||
int delay = LOG_RESTART_DELAY;
|
||||
|
||||
|
||||
/*
|
||||
* roll the local port forward so that we dont collide
|
||||
* with the first port assigned when we reboot
|
||||
*/
|
||||
logClientRollLocalPort();
|
||||
|
||||
while (1) {
|
||||
semTake(iocLogSignal, delay);
|
||||
|
||||
/*
|
||||
* mutex on
|
||||
*/
|
||||
status = semTake(iocLogMutex, WAIT_FOREVER);
|
||||
assert(status==OK);
|
||||
|
||||
if (iocLogFile==NULL) {
|
||||
reattach = TRUE;
|
||||
}
|
||||
else {
|
||||
reattach = ferror(iocLogFile);
|
||||
}
|
||||
|
||||
/*
|
||||
* mutex off
|
||||
*/
|
||||
status = semGive(iocLogMutex);
|
||||
assert(status==OK);
|
||||
|
||||
if (reattach==FALSE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* restart log server
|
||||
*/
|
||||
iocLogConnectCount = 0U;
|
||||
logClientRollLocalPort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* logClientRollLocalPort()
|
||||
*/
|
||||
LOCAL void logClientRollLocalPort(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
/*
|
||||
* roll the local port forward so that we dont collide
|
||||
* with it when we reboot
|
||||
*/
|
||||
while (iocLogConnectCount<10U) {
|
||||
/*
|
||||
* switch to a new log server connection
|
||||
*/
|
||||
status = iocLogAttach();
|
||||
if (status==OK) {
|
||||
/*
|
||||
* only print a message after the first connect
|
||||
*/
|
||||
if (iocLogConnectCount==1U) {
|
||||
printf(
|
||||
"iocLogClient: reconnected to the log server\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* if we cant connect then we will roll
|
||||
* the port later when we can
|
||||
* (we must not spin on connect fail)
|
||||
*/
|
||||
if (errno!=ETIMEDOUT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* logClientShutdown()
|
||||
*/
|
||||
LOCAL void logClientShutdown(void)
|
||||
{
|
||||
if (iocLogFD!=ERROR) {
|
||||
/*
|
||||
* unfortunately this does not currently work because WRS
|
||||
* runs the reboot hooks in the order the order that
|
||||
* they are installed (and the network is already shutdown
|
||||
* by the time we get here)
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* this aborts the connection because we
|
||||
* have specified a nill linger interval
|
||||
*/
|
||||
printf("log client: lingering for connection close...");
|
||||
close(iocLogFD);
|
||||
printf("done\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -151,8 +387,7 @@ iocLogInit()
|
||||
*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
getConfig()
|
||||
LOCAL int getConfig(void)
|
||||
{
|
||||
long status;
|
||||
|
||||
@@ -160,7 +395,7 @@ getConfig()
|
||||
&EPICS_IOC_LOG_PORT,
|
||||
&ioc_log_port);
|
||||
if(status<0){
|
||||
failureNoptify(&EPICS_IOC_LOG_PORT);
|
||||
failureNotify(&EPICS_IOC_LOG_PORT);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -168,7 +403,7 @@ getConfig()
|
||||
&EPICS_IOC_LOG_INET,
|
||||
&ioc_log_addr);
|
||||
if(status<0){
|
||||
failureNoptify(&EPICS_IOC_LOG_INET);
|
||||
failureNotify(&EPICS_IOC_LOG_INET);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
@@ -178,42 +413,59 @@ getConfig()
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* failureNotify()
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void
|
||||
failureNoptify(pparam)
|
||||
ENV_PARAM *pparam;
|
||||
LOCAL void failureNotify(ENV_PARAM *pparam)
|
||||
{
|
||||
logMsg( "IocLogClient: EPICS environment variable \"%s\" undefined\n",
|
||||
(int) pparam->name,
|
||||
0,0,0,0,0);
|
||||
epicsPrintf(
|
||||
"IocLogClient: EPICS environment variable \"%s\" undefined\n",
|
||||
pparam->name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* unused
|
||||
*
|
||||
*
|
||||
* iocLogVPrintf()
|
||||
*/
|
||||
#ifdef JUNKYARD
|
||||
ioTaskStdSet(taskIdSelf(), 1, sock);
|
||||
int iocLogVPrintf(const char *pFormat, va_list pvar)
|
||||
{
|
||||
int status;
|
||||
int semStatus;
|
||||
|
||||
while (1) {
|
||||
date();
|
||||
/*
|
||||
memShow(0);
|
||||
i(0);
|
||||
checkStack(0);
|
||||
*/
|
||||
/*
|
||||
* 60 min
|
||||
*/
|
||||
taskDelay(sysClkRateGet() * 60 * 60);
|
||||
if (!pFormat || iocLogDisable) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mutex on
|
||||
*/
|
||||
semStatus = semTake(iocLogMutex, WAIT_FOREVER);
|
||||
assert(semStatus==OK);
|
||||
|
||||
if (iocLogFile) {
|
||||
status = vfprintf(iocLogFile, pFormat, pvar);
|
||||
if (status>0) {
|
||||
status = fflush(iocLogFile);
|
||||
}
|
||||
|
||||
if (status<0) {
|
||||
logFdDelete(iocLogFD);
|
||||
fclose(iocLogFile);
|
||||
iocLogFile = NULL;
|
||||
iocLogFD = ERROR;
|
||||
semStatus = semGive(iocLogSignal);
|
||||
assert(semStatus==OK);
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = EOF;
|
||||
}
|
||||
|
||||
/*
|
||||
* mutex off
|
||||
*/
|
||||
semStatus = semGive(iocLogMutex);
|
||||
assert(semStatus==OK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -406,7 +406,7 @@ static void monitor(pcalc)
|
||||
/* check all input fields for changes*/
|
||||
for(i=0, pnew=&pcalc->a, pprev=&pcalc->la; i<ARG_MAX; i++, pnew++, pprev++) {
|
||||
if((*pnew != *pprev) || (monitor_mask&DBE_ALARM)) {
|
||||
db_post_events(pcalc,pnew,monitor_mask|DBE_VALUE);
|
||||
db_post_events(pcalc,pnew,monitor_mask|DBE_VALUE|DBE_LOG);
|
||||
*pprev = *pnew;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ static void monitor(psub)
|
||||
/* check all input fields for changes*/
|
||||
for(i=0, pnew=&psub->a, pprev=&psub->la; i<ARG_MAX; i++, pnew++, pprev++) {
|
||||
if(*pnew != *pprev) {
|
||||
db_post_events(psub,pnew,monitor_mask|DBE_VALUE);
|
||||
db_post_events(psub,pnew,monitor_mask|DBE_VALUE|DBE_LOG);
|
||||
*pprev = *pnew;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
USR_LDLIBS = -lca -lCom -lm -s
|
||||
USR_LDLIBS = -lca -lCom -lm
|
||||
DEPLIBS = $(EPICS_BASE_LIB)/libca.a $(EPICS_BASE_LIB)/libCom.a
|
||||
|
||||
SRCS.c = \
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
* .08 092292 joh improved message sent to the log
|
||||
* .09 050494 pg HPUX port changes.
|
||||
* .10 021694 joh ANSI C
|
||||
* $Log$
|
||||
* Revision 1.16 1995/11/08 23:48:26 jhill
|
||||
* improvents for better client reconnect
|
||||
*
|
||||
*/
|
||||
|
||||
static char *pSCCSID = "@(#)iocLogServer.c 1.9\t05/05/94";
|
||||
@@ -54,21 +58,27 @@ static char *pSCCSID = "@(#)iocLogServer.c 1.9\t05/05/94";
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
# ifdef SOLARIS
|
||||
# include <sys/filio.h>
|
||||
# endif
|
||||
|
||||
#include <bsdProto.h>
|
||||
|
||||
#include <envDefs.h>
|
||||
#include <fdmgr.h>
|
||||
|
||||
static long ioc_log_port;
|
||||
static unsigned short ioc_log_port;
|
||||
static long ioc_log_file_limit;
|
||||
static char ioc_log_file_name[64];
|
||||
|
||||
@@ -113,6 +123,7 @@ static int getConfig(void);
|
||||
static int openLogFile(struct ioc_log_server *pserver);
|
||||
static void handleLogFileError(void);
|
||||
static void envFailureNotify(ENV_PARAM *pparam);
|
||||
static void freeLogClient(struct iocLogClient *pclient);
|
||||
|
||||
|
||||
/*
|
||||
@@ -126,7 +137,7 @@ int main()
|
||||
struct timeval timeout;
|
||||
int status;
|
||||
struct ioc_log_server *pserver;
|
||||
int optval=1;
|
||||
int optval;
|
||||
|
||||
status = getConfig();
|
||||
if(status<0){
|
||||
@@ -158,6 +169,7 @@ int main()
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
optval = TRUE;
|
||||
status = setsockopt( pserver->sock,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
@@ -179,8 +191,8 @@ int main()
|
||||
sizeof (serverAddr) );
|
||||
if (status<0) {
|
||||
fprintf(stderr,
|
||||
"ioc log server allready installed on port %ld?\n",
|
||||
ioc_log_port);
|
||||
"iocLogServer: a server is already installed on port %u?\n",
|
||||
(unsigned)ioc_log_port);
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return ERROR;
|
||||
}
|
||||
@@ -192,6 +204,20 @@ int main()
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = ioctl(
|
||||
pserver->sock,
|
||||
FIONBIO,
|
||||
&optval);
|
||||
if(status<0){
|
||||
fprintf(stderr, "iocLogServer: %s\n", strerror(errno));
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = openLogFile(pserver);
|
||||
if(status<0){
|
||||
fprintf(stderr,
|
||||
@@ -201,10 +227,11 @@ int main()
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
status = fdmgr_add_fd(
|
||||
status = fdmgr_add_callback(
|
||||
pserver->pfdctx,
|
||||
pserver->sock,
|
||||
acceptNewClient,
|
||||
fdi_read,
|
||||
acceptNewClient,
|
||||
pserver);
|
||||
if(status<0){
|
||||
return ERROR;
|
||||
@@ -268,7 +295,7 @@ static void acceptNewClient(void *pParam)
|
||||
struct sockaddr_in addr;
|
||||
char *pname;
|
||||
int status;
|
||||
|
||||
int optval;
|
||||
|
||||
pclient = (struct iocLogClient *)
|
||||
malloc(sizeof *pclient);
|
||||
@@ -279,10 +306,28 @@ static void acceptNewClient(void *pParam)
|
||||
pclient->insock = accept(pserver->sock, NULL, 0);
|
||||
if(pclient->insock<0){
|
||||
free(pclient);
|
||||
fprintf(stderr, "Accept Error %d\n", errno);
|
||||
if (errno!=EWOULDBLOCK) {
|
||||
fprintf(stderr, "Accept Error %d\n", errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set non blocking IO
|
||||
* to prevent dead locks
|
||||
*/
|
||||
optval = TRUE;
|
||||
status = ioctl(
|
||||
pclient->insock,
|
||||
FIONBIO,
|
||||
&optval);
|
||||
if(status<0){
|
||||
close(pclient->insock);
|
||||
free(pclient);
|
||||
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
pclient->pserver = pserver;
|
||||
pclient->need_prefix = TRUE;
|
||||
pclient->ptopofstack = pclient->recvbuf;
|
||||
@@ -313,6 +358,7 @@ static void acceptNewClient(void *pParam)
|
||||
|
||||
logTime(pclient);
|
||||
|
||||
#if 0
|
||||
status = fprintf(
|
||||
pclient->pserver->poutfile,
|
||||
"%s %s ----- Client Connect -----\n",
|
||||
@@ -321,6 +367,7 @@ static void acceptNewClient(void *pParam)
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* turn on KEEPALIVE so if the client crashes
|
||||
@@ -340,11 +387,29 @@ static void acceptNewClient(void *pParam)
|
||||
}
|
||||
}
|
||||
|
||||
fdmgr_add_fd(
|
||||
pserver->pfdctx,
|
||||
pclient->insock,
|
||||
readFromClient,
|
||||
pclient);
|
||||
# define SOCKET_SHUTDOWN_WRITE_SIDE 1
|
||||
status = shutdown(pclient->insock, SOCKET_SHUTDOWN_WRITE_SIDE);
|
||||
if(status<0){
|
||||
close(pclient->insock);
|
||||
free(pclient);
|
||||
printf("%s:%d %s\n", __FILE__, __LINE__,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
status = fdmgr_add_callback(
|
||||
pserver->pfdctx,
|
||||
pclient->insock,
|
||||
fdi_read,
|
||||
readFromClient,
|
||||
pclient);
|
||||
if (status<0) {
|
||||
close(pclient->insock);
|
||||
free(pclient);
|
||||
fprintf(stderr, "%s:%d client fdmgr_add_callback() failed\n",
|
||||
__FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -362,66 +427,36 @@ static void readFromClient(void *pParam)
|
||||
int length;
|
||||
char *pcr;
|
||||
char *pline;
|
||||
unsigned stacksize;
|
||||
int stacksize;
|
||||
int size;
|
||||
|
||||
logTime(pclient);
|
||||
|
||||
stacksize = pclient->ptopofstack - pclient->recvbuf;
|
||||
length = read(pclient->insock,
|
||||
size = sizeof(pclient->recvbuf)-stacksize-1;
|
||||
assert(size>0);
|
||||
length = recv(pclient->insock,
|
||||
pclient->ptopofstack,
|
||||
sizeof(pclient->recvbuf)-stacksize-1);
|
||||
size,
|
||||
0);
|
||||
if (length <= 0) {
|
||||
|
||||
# ifdef DEBUG
|
||||
if(length == 0){
|
||||
fprintf(stderr, "iocLogServer: nil message disconnect\n");
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* flush any leftovers
|
||||
*/
|
||||
if(stacksize){
|
||||
status = fprintf(
|
||||
pclient->pserver->poutfile,
|
||||
"%s %s ",
|
||||
pclient->name,
|
||||
pclient->ascii_time);
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
}
|
||||
status = fwrite(
|
||||
pclient->recvbuf,
|
||||
stacksize,
|
||||
NITEMS,
|
||||
pclient->pserver->poutfile);
|
||||
if (status != NITEMS) {
|
||||
handleLogFileError();
|
||||
}
|
||||
status = fprintf(pclient->pserver->poutfile,"\n");
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
if (length<0) {
|
||||
if (errno != EWOULDBLOCK) {
|
||||
fprintf(stderr,
|
||||
"%s:%d socket=%d addr=%x size=%d read error=%s\n",
|
||||
__FILE__, __LINE__, pclient->insock,
|
||||
pclient->ptopofstack, size, strerror(errno));
|
||||
freeLogClient(pclient);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
status = fprintf(
|
||||
pclient->pserver->poutfile,
|
||||
"%s %s ----- Client Disconnect -----\n",
|
||||
pclient->name,
|
||||
pclient->ascii_time);
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
else {
|
||||
/*
|
||||
* disconnect
|
||||
*/
|
||||
freeLogClient(pclient);
|
||||
return;
|
||||
}
|
||||
|
||||
fdmgr_clear_fd(
|
||||
pclient->pserver->pfdctx,
|
||||
pclient->insock);
|
||||
if(close(pclient->insock)<0)
|
||||
abort();
|
||||
|
||||
free (pclient);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pclient->ptopofstack[length] = NULL;
|
||||
@@ -486,7 +521,76 @@ static void readFromClient(void *pParam)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* freeLogClient ()
|
||||
*/
|
||||
static void freeLogClient(struct iocLogClient *pclient)
|
||||
{
|
||||
unsigned stacksize;
|
||||
int status;
|
||||
|
||||
stacksize = pclient->ptopofstack - pclient->recvbuf;
|
||||
|
||||
# ifdef DEBUG
|
||||
if(length == 0){
|
||||
fprintf(stderr, "iocLogServer: nil message disconnect\n");
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* flush any left overs
|
||||
*/
|
||||
if(stacksize){
|
||||
status = fprintf(
|
||||
pclient->pserver->poutfile,
|
||||
"%s %s ",
|
||||
pclient->name,
|
||||
pclient->ascii_time);
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
}
|
||||
status = fwrite(
|
||||
pclient->recvbuf,
|
||||
stacksize,
|
||||
NITEMS,
|
||||
pclient->pserver->poutfile);
|
||||
if (status != NITEMS) {
|
||||
handleLogFileError();
|
||||
}
|
||||
status = fprintf(pclient->pserver->poutfile,"\n");
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
status = fprintf(
|
||||
pclient->pserver->poutfile,
|
||||
"%s %s ----- Client Disconnect -----\n",
|
||||
pclient->name,
|
||||
pclient->ascii_time);
|
||||
if(status<0){
|
||||
handleLogFileError();
|
||||
}
|
||||
#endif
|
||||
|
||||
status = fdmgr_clear_callback(
|
||||
pclient->pserver->pfdctx,
|
||||
pclient->insock,
|
||||
fdi_read);
|
||||
if (status!=OK) {
|
||||
fprintf(stderr, "%s:%d fdmgr_clear_callback() failed\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
if(close(pclient->insock)<0)
|
||||
abort();
|
||||
|
||||
free (pclient);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -524,21 +628,23 @@ static int getConfig(void)
|
||||
{
|
||||
int status;
|
||||
char *pstring;
|
||||
long param;
|
||||
|
||||
status = envGetLongConfigParam(
|
||||
&EPICS_IOC_LOG_PORT,
|
||||
&ioc_log_port);
|
||||
if(status<0){
|
||||
envFailureNotify(&EPICS_IOC_LOG_PORT);
|
||||
return ERROR;
|
||||
¶m);
|
||||
if(status>=0){
|
||||
ioc_log_port = (unsigned short) param;
|
||||
}
|
||||
else {
|
||||
ioc_log_port = 7004U;
|
||||
}
|
||||
|
||||
status = envGetLongConfigParam(
|
||||
&EPICS_IOC_LOG_FILE_LIMIT,
|
||||
&ioc_log_file_limit);
|
||||
if(status<0){
|
||||
envFailureNotify(&EPICS_IOC_LOG_FILE_LIMIT);
|
||||
return ERROR;
|
||||
ioc_log_file_limit = 10000;
|
||||
}
|
||||
|
||||
pstring = envGetConfigParam(
|
||||
|
||||
Reference in New Issue
Block a user