Compare commits

..

18 Commits

Author SHA1 Message Date
Michael Davidsaver
f5194b2274 older binutils compat 2018-12-13 11:22:07 -08:00
Michael Davidsaver
7bdbded47d travis-ci test rpath $ORIGIN 2018-11-20 22:00:42 -08:00
Michael Davidsaver
84831e13e7 epicsGetExecName WIN32, Darwin, solaris, freebsd 2018-11-20 22:00:42 -08:00
Michael Davidsaver
32340584b4 epicsGetExecDir() paths relative to executable
For linux, enable softIoc to find .dbd relative to the executable
location.

The same could be done for other targets

*bsd
  may have symlink /proc/curproc/file
  fallback to sysctl() with KERN_PROC_PATHNAME

solaris
  getexecname()

mac
  _NSGetExecutablePath()

WIN32
  GetModuleFileName(NULL)

others
  out of luck...
2018-11-20 22:00:42 -08:00
Michael Davidsaver
4ee3cbf382 LINKER_USE_RPATH=ORIGIN
Use Linux specific linker trick to allow relocation
of built tree.

relative rpath

use $ORIGIN to reference libraries in other modules
by relative path.

fix rel. RPATH
2018-11-20 22:00:42 -08:00
Michael Davidsaver
383b6b1c36 add aslibtest 2018-11-14 19:46:59 -08:00
Michael Davidsaver
bb19bd519e asLib add asInitMem() 2018-11-14 19:46:54 -08:00
Michael Davidsaver
d70bfed75b RTEMS: add zoneset() 2018-11-14 09:57:15 -08:00
Michael Davidsaver
3c2fe264cd epicsThreadRealtimeLock: clarify errors
give some more descriptive, linux specific, error messages
2018-11-14 09:55:19 -08:00
Michael Davidsaver
716f102dd6 rsrv: avoid redundant getpeername()
also do some extra, and redundant checks,
on accepted sockets.
2018-11-14 09:55:09 -08:00
Michael Davidsaver
cae597d21c ca: suppress repeated UDP error messages 2018-11-14 09:43:14 -08:00
Michael Davidsaver
c23012d081 rsrv: suppress repeated UDP error messages 2018-11-14 09:43:14 -08:00
Michael Davidsaver
30268e3577 ioc/db: dbRegisterServer() only warn on actual redefinition
avoid noise when simply run twice.
2018-11-04 20:04:05 -08:00
Michael Davidsaver
ebe7cf046e libCom: iocshRegisterVariable() only warn on actual redefinition
Avoid noise if simply called twice.
2018-11-04 19:32:48 -08:00
Andrew Johnson
00d937cc02 Don't parallelize test-results 2018-11-02 17:49:59 -05:00
Andrew Johnson
560f43b561 Use private server ports in netget test 2018-11-02 17:01:00 -05:00
Andrew Johnson
301ded2dc1 Fix detail in Release Checklist 2018-11-01 15:12:06 -05:00
Andrew Johnson
d3927dea91 Update version to -rc1-DEV after tagging. 2018-11-01 14:28:59 -05:00
39 changed files with 742 additions and 49 deletions

View File

@@ -73,5 +73,5 @@ make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make -j2 tapfiles
make -j2 -s test-results
make -s test-results
fi

View File

@@ -15,7 +15,7 @@ addons:
script:
- .ci/travis-build.sh
env:
- CMPLR=gcc
- CMPLR=gcc EXTRA=LINKER_USE_RPATH=ORIGIN
- CMPLR=clang
- CMPLR=gcc STATIC=YES
- CMPLR=clang STATIC=YES

View File

@@ -44,6 +44,8 @@ FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG) $(QUESTION_FLAG)
MAKERPATH = $(PYTHON) $(TOOLS)/makeRPath.py
#---------------------------------------------------------------
# tools for installing libraries and products
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG)

View File

@@ -60,8 +60,8 @@ EPICS_PATCH_LEVEL = 0
#EPICS_DEV_SNAPSHOT=-pre1-DEV
#EPICS_DEV_SNAPSHOT=-pre2
#EPICS_DEV_SNAPSHOT=-pre2-DEV
EPICS_DEV_SNAPSHOT=-rc1
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc1
EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
#EPICS_DEV_SNAPSHOT=

View File

@@ -38,6 +38,8 @@ BUILD_ARCHS = $(EPICS_HOST_ARCH) $(CROSS1) $(CROSS2)
# otherwise override this in os/CONFIG_SITE.<host_arch>.Common
PERL = perl -CSD
PYTHON = python
#-------------------------------------------------------
# Check configure/RELEASE file for consistency
CHECK_RELEASE_YES = checkRelease

View File

@@ -169,10 +169,17 @@ EPICS_SITE_VERSION =
GCC_PIPE = NO
# Set RPATH when linking executables and libraries.
# Must be either YES or NO. If you set this to NO you must also provide a
# Must be either YES, NO, or ORIGIN. If you set this to NO you must also provide a
# way for Base executables to find their shared libraries when they are
# run at build-time, e.g. set the LD_LIBRARY_PATH environment variable.
# ORIGIN is Linux specific.
LINKER_USE_RPATH = YES
# Only used when LINKER_USE_RPATH=ORIGIN
# The build time root of the relocatable tree.
# Linking to libraries under this root directory will be relative.
# Linking to libraries outside of this root will be absolute.
LINKER_ORIGIN_ROOT = $(INSTALL_LOCATION)
# Overrides for the settings above may appear in a CONFIG_SITE.local file
-include $(CONFIG)/CONFIG_SITE.local

View File

@@ -194,6 +194,13 @@ ifeq ($(EPICS_HOST_ARCH),$(T_A))
$(info Warning: RELEASE file consistency checks have been disabled)
endif
# $(FINAL_DIR) signals eventual install locations to makeRPath script
$(TESTPRODNAME): FINAL_DIR=.
$(PRODNAME): FINAL_DIR=$(INSTALL_BIN)
$(TESTSHRLIBNAME): FINAL_DIR=.
$(SHRLIBNAME): FINAL_DIR=$(INSTALL_SHRLIB)
$(LOADABLE_SHRLIBNAME): FINAL_DIR=$(INSTALL_SHRLIB)
#---------------------------------------------------------------
# The order of the following rules is
# VERY IMPORTANT !!!!

View File

@@ -25,11 +25,13 @@ STATIC_LDLIBS_YES= -Wl,-Bdynamic
# Set runtime path for shared libraries if USE_RPATH=YES and STATIC_BUILD=NO
SHRLIBDIR_RPATH_LDFLAGS_YES_NO = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_RPATH_LDFLAGS_ORIGIN_NO = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(SHRLIB_DEPLIB_DIRS))
SHRLIBDIR_LDFLAGS += \
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for products if USE_RPATH=YES and STATIC_BUILD=NO
PRODDIR_RPATH_LDFLAGS_YES_NO = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_RPATH_LDFLAGS_ORIGIN_NO = $(shell $(MAKERPATH) -O '\$$ORIGIN' -F $(FINAL_DIR) -R $(LINKER_ORIGIN_ROOT) $(PROD_DEPLIB_DIRS))
PRODDIR_LDFLAGS += \
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))

View File

@@ -160,7 +160,7 @@ made.</p>
files and directories that are only used for continuous integration:
<blockquote><tt>
cd base-7.0<br />
.ci/make-tar.sh R7.0.2-rc1 base-7.0.2-rc1.tar.gz base-7.0.2-rc1/
./.tools/make-tar.sh R7.0.2-rc1 base-7.0.2-rc1.tar.gz base-7.0.2-rc1/
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
@@ -303,7 +303,7 @@ made.</p>
files and directories that are only used for continuous integration:
<blockquote><tt>
cd base-7.0<br />
.ci/make-tar.sh R7.0.2 base-7.0.2.tar.gz base-7.0.2/
./.tools/make-tar.sh R7.0.2 base-7.0.2.tar.gz base-7.0.2/
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>

View File

@@ -961,7 +961,7 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
udpiiu :: SearchDestUDP :: SearchDestUDP (
const osiSockAddr & destAddr, udpiiu & udpiiuIn ) :
_destAddr ( destAddr ), _udpiiu ( udpiiuIn )
_lastError (0u), _destAddr ( destAddr ), _udpiiu ( udpiiuIn )
{
}
@@ -976,6 +976,13 @@ void udpiiu :: SearchDestUDP :: searchRequest (
int status = sendto ( _udpiiu.sock, const_cast<char *>(pBuf), bufSizeAsInt, 0,
& _destAddr.sa, sizeof ( _destAddr.sa ) );
if ( status == bufSizeAsInt ) {
if ( _lastError ) {
char buf[64];
sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
errlogPrintf (
"CAC: ok sending UDP msg to %s\n", buf);
}
_lastError = 0;
break;
}
if ( status >= 0 ) {
@@ -1002,7 +1009,9 @@ void udpiiu :: SearchDestUDP :: searchRequest (
else if ( localErrno == SOCK_EBADF ) {
break;
}
else {
else if ( localErrno == _lastError) {
break;
} else {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
@@ -1011,6 +1020,8 @@ void udpiiu :: SearchDestUDP :: searchRequest (
errlogPrintf (
"CAC: error = \"%s\" sending UDP msg to %s\n",
sockErrBuf, buf);
_lastError = localErrno;
break;
}
}

View File

@@ -123,6 +123,7 @@ private:
void show (
epicsGuard < epicsMutex > &, unsigned level ) const;
private:
int _lastError;
osiSockAddr _destAddr;
udpiiu & _udpiiu;
};

View File

@@ -12,6 +12,7 @@
#include <stddef.h>
#include <string.h>
#include "dbDefs.h"
#include "ellLib.h"
#include "envDefs.h"
#include "epicsStdio.h"
@@ -29,6 +30,7 @@ static char *stateNames[] = {
int dbRegisterServer(dbServer *psrv)
{
const char * ignore = envGetConfigParamPtr(&EPICS_IOC_IGNORE_SERVERS);
ELLNODE *node;
if (!psrv || !psrv->name || state != registering)
return -1;
@@ -55,10 +57,14 @@ int dbRegisterServer(dbServer *psrv)
}
}
if (ellNext(&psrv->node) || ellLast(&serverList) == &psrv->node) {
fprintf(stderr, "dbRegisterServer: '%s' registered twice?\n",
psrv->name);
return -1;
for(node=ellFirst(&serverList); node; node = ellNext(node)) {
dbServer *cur = CONTAINER(node, dbServer, node);
if(cur==psrv) {
return 0; /* already registered identically. */
} else if(strcmp(cur->name, psrv->name)==0) {
fprintf(stderr, "dbRegisterServer: Can't redefine '%s'.\n", cur->name);
return -1;
}
}
ellAdd(&serverList, &psrv->node);

View File

@@ -83,20 +83,22 @@ static void req_server (void *pParm)
while (TRUE) {
SOCKET clientSock;
struct sockaddr sockAddr;
osiSockAddr sockAddr;
osiSocklen_t addLen = sizeof(sockAddr);
while (castcp_ctl == ctlPause) {
epicsThreadSleep(0.1);
}
clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen );
if ( clientSock == INVALID_SOCKET ) {
clientSock = epicsSocketAccept ( IOC_sock, &sockAddr.sa, &addLen );
if ( clientSock == INVALID_SOCKET ||
sockAddr.sa.sa_family != AF_INET ||
addLen < sizeof(sockAddr.ia) ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf("CAS: Client accept error: %s\n",
sockErrBuf );
errlogPrintf("CAS: Client accept error: %s (%d)\n",
sockErrBuf, (int)addLen );
epicsThreadSleep(15.0);
continue;
}
@@ -105,7 +107,7 @@ static void req_server (void *pParm)
struct client *pClient;
/* socket passed in is closed if unsuccessful here */
pClient = create_tcp_client ( clientSock );
pClient = create_tcp_client ( clientSock, &sockAddr );
if ( ! pClient ) {
epicsThreadSleep ( 15.0 );
continue;
@@ -1405,12 +1407,11 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size )
/*
* create_tcp_client ()
*/
struct client *create_tcp_client ( SOCKET sock )
struct client *create_tcp_client (SOCKET sock , const osiSockAddr *peerAddr)
{
int status;
struct client *client;
int intTrue = TRUE;
osiSocklen_t addrSize;
unsigned priorityOfEvents;
/* socket passed in is destroyed here if unsuccessful */
@@ -1419,6 +1420,8 @@ struct client *create_tcp_client ( SOCKET sock )
return NULL;
}
client->addr = peerAddr->ia;
/*
* see TCP(4P) this seems to make unsolicited single events much
* faster. I take care of queue up as load increases.
@@ -1470,15 +1473,6 @@ struct client *create_tcp_client ( SOCKET sock )
}
#endif
addrSize = sizeof ( client->addr );
status = getpeername ( sock, (struct sockaddr *)&client->addr,
&addrSize );
if ( status < 0 ) {
epicsPrintf ("CAS: peer address fetch failed\n");
destroy_tcp_client (client);
return NULL;
}
client->evuser = (struct event_user *) db_init_events ();
if ( ! client->evuser ) {
errlogPrintf ("CAS: unable to init the event facility\n");

View File

@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <cantProceed.h>
#include "addrList.h"
#include "dbDefs.h"
@@ -45,6 +46,7 @@ void rsrv_online_notify_task(void *pParm)
caHdr msg;
int status;
ca_uint32_t beaconCounter = 0;
int *lastError;
taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
@@ -70,29 +72,45 @@ void rsrv_online_notify_task(void *pParm)
msg.m_count = htons (ca_server_port);
msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
/* beaconAddrList should not change after rsrv_init(), which then starts this thread */
lastError = callocMustSucceed(ellCount(&beaconAddrList), sizeof(*lastError), "rsrv_online_notify_task lastError");
epicsEventSignal(beacon_startStopEvent);
while (TRUE) {
ELLNODE *cur;
unsigned i;
/* send beacon to each interface */
for(cur=ellFirst(&beaconAddrList); cur; cur=ellNext(cur))
for(i=0, cur=ellFirst(&beaconAddrList); cur; i++, cur=ellNext(cur))
{
osiSockAddrNode *pAddr = CONTAINER(cur, osiSockAddrNode, node);
status = sendto (beaconSocket, (char *)&msg, sizeof(msg), 0,
&pAddr->addr.sa, sizeof(pAddr->addr));
if (status < 0) {
char sockErrBuf[64];
char sockDipBuf[22];
int err = SOCKERRNO;
if(err != lastError[i]) {
char sockErrBuf[64];
char sockDipBuf[22];
epicsSocketConvertErrnoToString(sockErrBuf, sizeof(sockErrBuf));
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
errlogPrintf ( "CAS: CA beacon send to %s error: %s\n",
sockDipBuf, sockErrBuf);
epicsSocketConvertErrorToString(sockErrBuf, sizeof(sockErrBuf), err);
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
errlogPrintf ( "CAS: CA beacon send to %s error: %s\n",
sockDipBuf, sockErrBuf);
lastError[i] = err;
}
}
else {
assert (status == sizeof(msg));
if(lastError[i]) {
char sockDipBuf[22];
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
errlogPrintf ( "CAS: CA beacon send to %s ok\n",
sockDipBuf);
}
lastError[i] = 0;
}
}
@@ -111,6 +129,8 @@ void rsrv_online_notify_task(void *pParm)
delay = 0.02; /* Restart beacon timing if paused */
}
}
free(lastError);
}

View File

@@ -230,7 +230,7 @@ void rsrv_online_notify_task (void *);
void cast_server (void *);
struct client *create_client ( SOCKET sock, int proto );
void destroy_client ( struct client * );
struct client *create_tcp_client ( SOCKET sock );
struct client *create_tcp_client ( SOCKET sock, const osiSockAddr* peerAddr );
void destroy_tcp_client ( struct client * );
void casAttachThreadToClient ( struct client * );
int camessage ( struct client *client );

View File

@@ -62,23 +62,59 @@
#include "epicsThread.h"
#include "epicsExit.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "dbStaticLib.h"
#include "subRecord.h"
#include "dbAccess.h"
#include "asDbLib.h"
#include "iocInit.h"
#include "iocsh.h"
#include "osiFileName.h"
#include "epicsInstallDir.h"
extern "C" int softIoc_registerRecordDeviceDriver(struct dbBase *pdbbase);
#define DBD_FILE EPICS_BASE "/dbd/softIoc.dbd"
#define EXIT_FILE EPICS_BASE "/db/softIocExit.db"
#define DBD_BASE "dbd/softIoc.dbd"
#define EXIT_BASE "db/softIocExit.db"
#define DBD_FILE_REL "../../" DBD_BASE
#define EXIT_FILE_REL "../../" EXIT_BASE
#define DBD_FILE EPICS_BASE "/" DBD_BASE
#define EXIT_FILE EPICS_BASE "/" EXIT_BASE
const char *arg0;
const char *base_dbd = DBD_FILE;
const char *exit_db = EXIT_FILE;
static void preparePath(void)
{
FILE *fp;
char *prefix = epicsGetExecDir();
char *dbd, *exit;
if(!prefix) return;
dbd = (char*)malloc(strlen(prefix) + strlen(DBD_FILE_REL) + 1);
if(dbd) {
dbd[0] = '\0';
strcat(dbd, prefix);
strcat(dbd, DBD_FILE_REL);
printf("Testing '%s'\n", dbd);
if((fp = fopen(dbd, "rb"))!=NULL) {
fclose(fp);
base_dbd = dbd;
}
}
exit = (char*)malloc(strlen(prefix) + strlen(EXIT_FILE_REL) + 1);
if(exit) {
exit[0] = '\0';
strcat(exit, prefix);
strcat(exit, EXIT_FILE_REL);
if((fp = fopen(exit, "rb"))!=NULL) {
fclose(fp);
exit_db = exit;
}
}
}
static void exitSubroutine(subRecord *precord) {
epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
@@ -96,6 +132,7 @@ static void usage(int status) {
int main(int argc, char *argv[])
{
preparePath();
char *dbd_file = const_cast<char*>(base_dbd);
char *macros = NULL;
char xmacro[PVNAME_STRINGSZ + 4];

View File

@@ -79,6 +79,11 @@ dbServer one = {
oneInit, oneRun, onePause, oneStop
};
dbServer one2 = {
ELLNODE_INIT, "one",
oneReport, oneStats, oneClient,
oneInit, oneRun, onePause, oneStop
};
/* Server layer for testing NULL methods */
@@ -123,7 +128,7 @@ MAIN(dbServerTest)
char *theName = "The One";
int status;
testPlan(24);
testPlan(25);
/* Prove that we handle substring names properly */
epicsEnvSet("EPICS_IOC_IGNORE_SERVERS", "none ones");
@@ -132,7 +137,8 @@ MAIN(dbServerTest)
testOk(dbRegisterServer(&one) == 0, "Registered 'one'");
testOk1(oneState == NOTHING_CALLED);
testOk(dbRegisterServer(&one) != 0, "Duplicate registration rejected");
testOk(dbRegisterServer(&one) == 0, "Duplicate registration accepted");
testOk(dbRegisterServer(&one2) != 0, "change registration rejected");
testOk(dbRegisterServer(&illegal) != 0, "Illegal registration rejected");
testDiag("Registering dbServer 'no-routines'");

View File

@@ -13,9 +13,12 @@ $ENV{HARNESS_ACTIVE} = 1 if scalar @ARGV && shift eq '-tap';
# Keep traffic local and avoid duplicates over multiple interfaces
$ENV{EPICS_CA_AUTO_ADDR_LIST} = 'NO';
$ENV{EPICS_CA_ADDR_LIST} = 'localhost';
$ENV{EPICS_CA_SERVER_PORT} = 55064;
$ENV{EPICS_CAS_INTF_ADDR_LIST} = 'localhost';
$ENV{EPICS_PVA_AUTO_ADDR_LIST} = 'NO';
$ENV{EPICS_PVA_ADDR_LIST} = 'localhost';
$ENV{EPICS_PVA_SERVER_PORT} = 55076;
$ENV{EPICS_PVAS_INTF_ADDR_LIST} = 'localhost';
my $bin = "@TOP@/bin/@ARCH@";

View File

@@ -509,6 +509,25 @@ static void nfsMountCallFunc(const iocshArgBuf *args)
}
#endif
void zoneset(const char *zone)
{
if(zone)
setenv("TZ", zone, 1);
else
unsetenv("TZ");
tzset();
}
static const iocshArg zonesetArg0 = {"zone string", iocshArgString};
static const iocshArg * const zonesetArgs[1] = {&zonesetArg0};
static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs};
static void zonesetCallFunc(const iocshArgBuf *args)
{
zoneset(args[0].sval);
}
/*
* Register RTEMS-specific commands
*/
@@ -519,6 +538,7 @@ static void iocshRegisterRTEMS (void)
#ifndef OMIT_NFS_SUPPORT
iocshRegister(&nfsMountFuncDef, nfsMountCallFunc);
#endif
iocshRegister(&zonesetFuncDef, &zonesetCallFunc);
}
/*

View File

@@ -66,6 +66,7 @@ epicsShareFunc long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction);
epicsShareFunc long epicsShareAPI asInitFile(
const char *filename,const char *substitutions);
epicsShareFunc long epicsShareAPI asInitFP(FILE *fp,const char *substitutions);
epicsShareFunc long epicsShareAPI asInitMem(const char *acf, const char *substitutions);
/*caller must provide permanent storage for asgName*/
epicsShareFunc long epicsShareAPI asAddMember(
ASMEMBERPVT *asMemberPvt,const char *asgName);

View File

@@ -250,7 +250,35 @@ long epicsShareAPI asInitFP(FILE *fp,const char *substitutions)
}
return(status);
}
static const char* membuf;
static int memInputFunction(char *buf, int max_size)
{
int ret = 0;
if(!membuf) return ret;
while(max_size && *membuf) {
*buf++ = *membuf++;
max_size--;
ret++;
}
return ret;
}
long epicsShareAPI asInitMem(const char *acf, const char *substitutions)
{
long ret = S_asLib_InitFailed;
if(!acf) return ret;
membuf = acf;
ret = asInitialize(&memInputFunction);
membuf = NULL;
return ret;
}
long epicsShareAPI asAddMember(ASMEMBERPVT *pasMemberPvt,const char *asgName)
{
long status;

View File

@@ -178,9 +178,11 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef)
for (l = NULL, p = iocshVariableHead ; p != NULL ; l = p, p = p->next) {
i = strcmp (piocshVarDef->name, p->pVarDef->name);
if (i == 0) {
errlogPrintf("Warning: iocshRegisterVariable redefining %s.\n",
piocshVarDef->name);
p->pVarDef = piocshVarDef;
if (p->pVarDef != piocshVarDef) {
errlogPrintf("Warning: iocshRegisterVariable redefining %s.\n",
piocshVarDef->name);
p->pVarDef = piocshVarDef;
}
found = 1;
break;
}

View File

@@ -14,7 +14,29 @@
#ifndef unixFileNameH
#define unixFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ":"
#define OSI_PATH_SEPARATOR "/"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* unixFileNameH */

View File

@@ -123,6 +123,7 @@ Com_SRCS += osdMonotonic.c
Com_SRCS += osdProcess.c
Com_SRCS += osdNetIntf.c
Com_SRCS += osdMessageQueue.c
Com_SRCS += osdgetexec.c
Com_SRCS += devLibVME.c
Com_SRCS += devLibVMEOSD.c

View File

@@ -0,0 +1,50 @@
#include <string.h>
#include <stdlib.h>
#include <mach-o/dyld.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
uint32_t max = 64u;
char *ret = NULL;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
/* cf. "man 3 dyld" */
if(_NSGetExecutablePath(ret, &max)==0) {
/* max left unchanged */
ret[max-1] = '\0';
break;
}
/* max has been updated with required size */
}
/* TODO: _NSGetExecutablePath() doesn't follow symlinks */
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -0,0 +1,54 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = PATH_MAX;
char *ret = NULL;
ssize_t n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = readlink("/proc/self/exe", ret, max);
if(n == -1) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
/* readlink() never adds a nil */
ret[n] = '\0';
break;
}
max += 64;
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -0,0 +1,52 @@
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = 128;
char *ret = NULL;
DWORD n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = GetModuleFileName(NULL, ret, max);
if(n == 0) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
ret[n] = '\0';
break;
}
max += 64;
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '\\');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -15,7 +15,29 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -14,7 +14,29 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -0,0 +1,14 @@
#include <stdlib.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
return NULL;
}
char *epicsGetExecDir(void)
{
return NULL;
}

View File

@@ -0,0 +1,68 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = PATH_MAX;
char *ret = NULL;
ssize_t n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = readlink("/proc/curproc/file", ret, max);
if(n == -1) {
free(ret);
ret = NULL;
break;
} else if(n < max) {
/* readlink() never adds a nil */
ret[n] = '\0';
break;
}
max += 64;
}
if(!ret) {
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PATHNAME;
mib[3] = -1;
ret = malloc(max);
if(ret) {
sysctl(mib, 4, ret, &cb, NULL, 0);
/* TODO: error check */
}
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -422,9 +422,24 @@ void epicsThreadRealtimeLock(void)
int status = mlockall(MCL_CURRENT | MCL_FUTURE);
if (status) {
fprintf(stderr, "epicsThreadRealtimeLock "
"Warning: Unable to lock the virtual address space.\n"
"VM page faults may harm real-time performance.\n");
const int err = errno;
switch(err) {
#ifdef __linux__
case ENOMEM:
fprintf(stderr, "epicsThreadRealtimeLock "
"Warning: unable to lock memory. RLIMIT_MEMLOCK is too small or missing CAP_IPC_LOCK\n");
break;
case EPERM:
fprintf(stderr, "epicsThreadRealtimeLock "
"Warning: unable to lock memory. missing CAP_IPC_LOCK\n");
break;
#endif
default:
fprintf(stderr, "epicsThreadRealtimeLock "
"Warning: Unable to lock the virtual address space.\n"
"VM page faults may harm real-time performance. errno=%d\n",
err);
}
}
}
#endif

View File

@@ -0,0 +1,30 @@
#include <string.h>
#include <stdlib.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
const char *raw = getexecname();
char *ret = NULL;
/* manpage says getexecname() might return a relative path. we treat this as an error */
if(raw[0]=='/') {
ret = strdup(raw);
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -194,6 +194,11 @@ macLibTest_SRCS += macLibTest.c
testHarness_SRCS += macLibTest.c
TESTS += macLibTest
TESTPROD_HOST += aslibtest
aslibtest_SRCS += aslibtest.c
testHarness_SRCS += aslibtest.c
TESTS += aslibtest
# Perl module tests:
TESTS += macLib
@@ -227,6 +232,11 @@ osiSockTest_SRCS += osiSockTest.c
testHarness_SRCS += osiSockTest.c
TESTS += osiSockTest
TESTPROD_HOST += testexecname
testexecname_SRCS += testexecname.c
# no point in including in testHarness. Not implemented for RTEMS/vxWorks.
TESTS += testexecname
ifeq ($(BUILD_CLASS),HOST)
ifneq ($(OS_CLASS),WIN32)
# This test can only be run on a build host, and is broken on Windows

View File

@@ -0,0 +1,119 @@
/*************************************************************************\
* Copyright (c) 2018 Michael Davidsaver
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <testMain.h>
#include <epicsUnitTest.h>
#include <errSymTbl.h>
#include <epicsString.h>
#include <osiFileName.h>
#include <errlog.h>
#include <asLib.h>
static char *asUser,
*asHost;
static int asAsl;
static void setUser(const char *name)
{
free(asUser);
asUser = epicsStrDup(name);
}
static void setHost(const char *name)
{
free(asHost);
asHost = epicsStrDup(name);
}
static void testAccess(const char *asg, unsigned mask)
{
ASMEMBERPVT asp = 0; /* aka dbCommon::asp */
ASCLIENTPVT client = 0;
long ret;
ret = asAddMember(&asp, asg);
if(ret) {
testFail("testAccess(ASG:%s, USER:%s, HOST:%s, ASL:%d) -> asAddMember error: %s",
asg, asUser, asHost, asAsl, errSymMsg(ret));
} else {
ret = asAddClient(&client, asp, asAsl, asUser, asHost);
}
if(ret) {
testFail("testAccess(ASG:%s, USER:%s, HOST:%s, ASL:%d) -> asAddClient error: %s",
asg, asUser, asHost, asAsl, errSymMsg(ret));
} else {
unsigned actual = 0;
actual |= asCheckGet(client) ? 1 : 0;
actual |= asCheckPut(client) ? 2 : 0;
testOk(actual==mask, "testAccess(ASG:%s, USER:%s, HOST:%s, ASL:%d) -> %x == %x",
asg, asUser, asHost, asAsl, actual, mask);
}
if(client) asRemoveClient(&client);
if(asp) asRemoveMember(&asp);
}
static void testSyntaxErrors(void)
{
static const char empty[] = "\n#almost empty file\n\n";
long ret;
testDiag("testSyntaxErrors()");
eltc(0);
ret = asInitMem(empty, NULL);
testOk(ret==S_asLib_badConfig, "load \"empty\" config -> %s", errSymMsg(ret));
eltc(1);
}
static const char hostname_config[] = ""
"HAG(foo) {localhost}\n"
"ASG(DEFAULT) {RULE(0, NONE)}\n"
"ASG(ro) {RULE(0, NONE)RULE(1, READ) {HAG(foo)}}\n"
"ASG(rw) {RULE(1, WRITE) {HAG(foo)}}\n"
;
static void testHostNames(void)
{
testDiag("testHostNames()");
testOk1(asInitMem(hostname_config, NULL)==0);
setUser("testing");
setHost("localhost");
asAsl = 0;
testAccess("invalid", 0);
testAccess("DEFAULT", 0);
testAccess("ro", 1);
testAccess("rw", 3);
setHost("127.0.0.1");
testAccess("invalid", 0);
testAccess("DEFAULT", 0);
testAccess("ro", 0);
testAccess("rw", 0);
setHost("nosuchhost");
testAccess("invalid", 0);
testAccess("DEFAULT", 0);
testAccess("ro", 0);
testAccess("rw", 0);
}
MAIN(aslibtest)
{
testPlan(14);
testSyntaxErrors();
testHostNames();
errlogFlush();
return testDone();
}

View File

@@ -16,6 +16,7 @@
#include <epicsThread.h>
#include <epicsUnitTest.h>
int aslibtest(void);
int blockingSockTest(void);
int epicsAlgorithm(void);
int epicsAtomicTest(void);
@@ -73,6 +74,7 @@ void epicsRunLibComTests(void)
/*
* Run the regular tests in alphabetical order
*/
runTest(aslibtest);
runTest(blockingSockTest);
runTest(epicsAlgorithm);
runTest(epicsAtomicTest);

View File

@@ -0,0 +1,24 @@
#include <string.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <osiFileName.h>
MAIN(testexecname)
{
testPlan(1);
{
char *buf = epicsGetExecName();
if(!buf) {
testSkip(1, "epicsGetExecName() not available for this target");
} else {
char *loc = strstr(buf, "testexecname");
testOk(!!loc, "Find \"testexecname\" in \"%s\"", buf);
}
}
return testDone();
}

View File

@@ -39,6 +39,8 @@ PERL_SCRIPTS += tap-to-junit-xml.pl
PERL_SCRIPTS += useManifestTool.pl
PERL_SCRIPTS += genVersionHeader.pl
PERL_SCRIPTS += makeRPath.py
HTMLS = style.css
HTMLS += EPICS/Getopts.html
HTMLS += EPICS/Path.html

37
src/tools/makeRPath.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python
from __future__ import print_function
import sys
import os
from argparse import ArgumentParser
if os.environ.get('EPICS_DEBUG_RPATH','')=='YES':
sys.stderr.write('%s'%sys.argv)
P = ArgumentParser()
P.add_argument('-F','--final',default=os.getcwd(), help='Final install location for ELF file')
P.add_argument('-R','--root',default='/')
P.add_argument('-O', '--origin', default='$ORIGIN')
P.add_argument('path', nargs='*')
args = P.parse_args()
fdir = os.path.abspath(args.final)
output = []
for path in args.path:
path = os.path.abspath(path)
if args.root and os.path.relpath(path, args.root).startswith('../'):
pass # absolute rpath
else:
# some older binutils don't seem to handle $ORIGIN correctly
# when locating dependencies of libraries. So also provide
# the absolute path for internal use by 'ld' only.
output.append('-Wl,-rpath-link,'+path)
path = os.path.relpath(path, fdir)
output.append('-Wl,-rpath,'+os.path.join(args.origin, path))
print(' '.join(output))