EPICS Controls Argonne National Laboratory

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  2020  2021  2022  2023  2024  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  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: read waveform data using ca_create_subscription
From: 吴煊 <[email protected]>
To: tech-talk <[email protected]>
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  2020  2021  2022  2023  2024 
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  2020  2021  2022  2023  2024 
ANJ, 17 Dec 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·