EPICS Home

Experimental Physics and Industrial Control System


 
1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019 
<== Date ==> <== Thread ==>

Subject: read waveform data using ca_create_subscription
From: 吴煊 <wux@ihep.ac.cn>
To: tech-talk <tech-talk@aps.anl.gov>
Date: Fri, 31 Oct 2014 09:06:14 +0800 (GMT+08:00)
Hi All,

   I write a simple CA program to read waveform data. If I monitor less than 41 waveform PVs(100 elements of float type and 25Hz scan rate), it works fine. If I monitor 42 or more(modify "CH_NUM" in archive.c), then segmentation fault occured. I used gdb to debug it.
(gdb) bt
#0  ca_element_count (pChan=0x31346677) at ../oldChannelNotify.cpp:634
#1  0x0000000000400fe3 in main (argc=<value optimized out>, argv=<value optimized out>) at archive.c:138
(gdb) where
#0  ca_element_count (pChan=0x31346677) at ../oldChannelNotify.cpp:634
#1  0x0000000000400fe3 in main (argc=<value optimized out>, argv=<value optimized out>) at archive.c:138
(gdb) l
629	/*
630	 * ca_element_count ()
631	 */
632	arrayElementCount epicsShareAPI ca_element_count ( chid pChan ) 
633	{
634	    epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
635	    return pChan->io.nativeElementCount ( guard );
636	}
637	
638	/*

It seems that there is something wrong with "ca_element_count" and "epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );"
Then I used fixed count number 100 instead of using "ca_element_count", segment fault as well.
(gdb) bt
#0  ca_create_subscription (type=16, count=100, pChan=0x31346677, mask=5, pCallBack=0x401250 <monitor>, pCallBackArg=0x7fffc71f9470, monixptr=0x0) at ../oldChannelNotify.cpp:560
#1  0x0000000000400fd9 in main (argc=<value optimized out>, argv=<value optimized out>) at archive.c:141
(gdb) l
555	    if ( mask & ~maskMask ) {
556	        return ECA_BADMASK;
557	    }
558	
559	    try {
560	        epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
561	        try {
562	            // if this stalls out on a live circuit then an exception 
563	            // can be forthcoming which we must ignore (this is a
564	            // special case preserving legacy ca_create_subscription

I guess there is something to do with "epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );"  However, I don't know whether my code having bug or something else wrong. Any help will be appreciate 

I'm using RedHat 6.5_x64 and EPICS base 3.14.12.1

Cheers

Xuan Wu
IHEP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cadef.h>
#include <signal.h>

#define epicsAlarmGLOBAL
#include <alarm.h>

#define CH_NUM 42
#define MAX_STRING 40
#define TIME_OUT 5.0

FILE *fp;

void SetQuit(int sig)
{
	fclose(fp);
	printf("\nWarning!!!Stop signal is sent\n");
	exit(0);
}

typedef struct 
{
    chid channel;
    struct dbr_time_float *data;
} epicsFloatPV;

const char *channel_state_str[4] = {
    "not found",
    "connection lost",
    "connected",
    "closed"
};

void printFloatPV(const epicsFloatPV* pv)
{
	char timeString[32];
	const dbr_float_t * pValue;
	int i;
	unsigned int count;

    if (ca_state(pv->channel) != cs_conn)
    {
        printf("%s <%s>\n",
            ca_name(pv->channel),
            channel_state_str[ca_state(pv->channel)]);
        return;
    }

	epicsTimeToStrftime (timeString, sizeof(timeString), "%Y-%m-%d %H:%M:%S.%06f", &pv->data->stamp);
	count = ca_element_count(pv->channel);
   // printf("%s %s", ca_name(pv->channel), timeString);
    fprintf(fp, "%s %s %d", ca_name(pv->channel), timeString, count);

	pValue = &pv->data->value;
	for(i=0; i<count; i++)
	{
	//	printf(" %f", pValue[i]);
		fprintf(fp, " %f", pValue[i]);
	}
	fprintf(fp, "\n");

    if (pv->data->severity != NO_ALARM)
    {
        printf(" <%s %s>\n",
            epicsAlarmSeverityStrings[pv->data->severity],
            epicsAlarmConditionStrings[pv->data->status]);
    }
}

static void monitor(struct event_handler_args args)
{
    if (args.status != ECA_NORMAL)
    {
        /* Something went wrong. */
        SEVCHK(args.status, "monitor");
        return;
    }
    /* Let's have a look at the type of the data.
 *        It should be one of the types that we have requested.
 *            */
    switch (args.type)
    {
        case DBR_TIME_FLOAT:
            {
				epicsFloatPV *pv = args.usr;
	            memcpy(pv->data, args.dbr, dbr_size_n(args.type, args.count));
    	        printFloatPV(pv);
                break;
            }
        default:
            printf ("%s unsupported data type\n", ca_name(args.chid));
    }
}

int main(int argc, char **argv)
{
	int stat;
	epicsFloatPV pv[CH_NUM];
	int index;
	char chName[MAX_STRING][CH_NUM];
	struct sigaction act;

	act.sa_handler = SetQuit;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGINT, &act, 0);		//signal Ctrl+c

	if((fp = fopen("data", "a+")) == NULL)
	{
		printf("can't open data file\n");
		exit(0);
	}
	/* Initialize */
    stat=ca_context_create(ca_disable_preemptive_callback);
    if(stat != ECA_NORMAL)
	{
		printf("ca_context_create failed:\n%s\n",ca_message(stat));
		exit(1);
    }

	/* Search */
	for(index=0; index<CH_NUM; index++)
	{
		sprintf(chName[index], "wf%d", index+1);	
		stat=ca_create_channel(chName[index],NULL,NULL,CA_PRIORITY_DEFAULT,&pv[index].channel);
	    if(stat != ECA_NORMAL) 
		{
			printf("ca_create_channel failed:\n%s\n",ca_message(stat));
			exit(1);
    	}
	}

	SEVCHK(ca_pend_io(TIME_OUT), "ca_search");
	for(index=0; index<CH_NUM; index++)
	{
		pv[index].data = malloc(dbr_size_n(DBF_FLOAT, ca_element_count(pv[index].channel)));
		ca_create_subscription(DBR_TIME_FLOAT, ca_element_count(pv[index].channel), pv[index].channel, DBE_VALUE|DBE_ALARM, monitor, &pv[index], NULL);
//		pv[index].data = malloc(dbr_size_n(DBF_FLOAT, 100));
//		ca_create_subscription(DBR_TIME_FLOAT, 100, pv[index].channel, DBE_VALUE|DBE_ALARM, monitor, &pv[index], NULL);
	}

	SEVCHK(ca_flush_io(), "ca_add_event");

	/* Process search */
	/*stat=ca_pend_io(TIME_OUT);*/
	stat=ca_pend_event(0);
    if(stat != ECA_NORMAL) 
	{
		printf("ca_pend_io timed out for search after %g sec\n", TIME_OUT);
		exit(1);
    }

	/* Clear the channel */
	for(index=0; index<CH_NUM; index++)
	{
    	stat=ca_clear_channel(pv[index].channel);
    	if(stat != ECA_NORMAL) 
		{
			printf("ca_clear_channel failed:\n%s\n",ca_message(stat));
    	}
    	// after ca_clear_channel, no monitor should come any more. So now we can free the buffer.
    	free(pv[index].data);
	}
    
	/* Exit */
    ca_context_destroy();
//	fclose(fp);
	printf("\nDone\n");
    return(0);
}

Attachment: Makefile
Description: Binary data

Attachment: test.db
Description: Binary data


Replies:
Re: read waveform data using ca_create_subscription Bruce Hill

Navigate by Date:
Prev: RE: Serial device server timeouts, overwhelmed by load? Mark Rivers
Next: Re: Problem with CSS archive engine 龙巍
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019 
Navigate by Thread:
Prev: RE: Serial device server timeouts, overwhelmed by load? jon
Next: Re: read waveform data using ca_create_subscription Bruce Hill
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019