Problem: Single instance of an executable

Hello,

Is there a way to ensure that a program has only a single instance running (on neutrino)?

Previously on QNX4…it could be done using qnx_name_attach and qnx_name_locate. Is it a direct mapping to name_attach and name_open?
Or is there a better way to do it?

Rgds

Yes pretty much. Althouth there are race condition to take care of (even under QNX4).

Well if nothing else is more convient, you could always write a simple resource manager to do this.

Thank you for your replies.

Mario - Race condition? Is it handling the EBUSY or the _IO_CONNECT?

Maschoen - Can you please point me to an example or provide one if it is not too much of a trouble?

Rgds

Yeah but it’s still a mess because you need to have redundancies (in case of a network scenario). The gns is already a resource manager ;-)

Hmm…looks like I was not on the wrong path after all. :smiley:

So I hope the skeleton:

Step1: name_open with tests for - a return of -1 and then errno for EBUSY, followed by an exit.
Step2: name_attach with a MsgReply of EOK for a _IO_CONNECT
Step3: name_open for any further processing

would be the basic principle for ensuring the single instance?

Rgds

This is an overly simplistic solution. I could easily be expanded to handler multiple different programs. You could also hide the client interface fairly easily. If the code looks familiar, it mostly right out of Robert Krytn’s book “Getting Started with QNX Neutrion 2”

singl_mgr.c:
#include <libc.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
char device_name[64] = "/dev/mypgm";
//
//	This variable is either 0 or 1 indicating whether the program is already 
//		running
//
#define TRUE		1
#define FALSE		0
int opened;
int io_open(resmgr_context_t *ctp, io_open_t *msg, 
	RESMGR_HANDLE_T *handle, void *extra);
int io_close(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb);

int main (int argc, char **argv)
{
	dispatch_t 					*dpp;
	resmgr_attr_t				resmgr_attr;
	resmgr_context_t			*ctp;
	resmgr_connect_funcs_t		cfuncs;
	resmgr_io_funcs_t			ifuncs;
	iofunc_attr_t				attr;

	if (argc > 1)
	{
		if (argv[1][0] == '-' && argv[1][1] == 'n')
		{
			strcpy(device_name,argv[1]+2);
		}
	}
	fprintf(stderr,"%s: using name %s\n",argv[0],device_name);

	if ((dpp = dispatch_create()) == NULL)
	{
		perror("error: dispatch_create\n");
		exit(EXIT_FAILURE);
	}

	iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
	memset(&resmgr_attr, 0, sizeof(resmgr_attr));
	resmgr_attr.nparts_max = 1;
	resmgr_attr.msg_max_size = 2048;

	iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &cfuncs,
		_RESMGR_IO_NFUNCS, &ifuncs);

	cfuncs.open = &io_open;
	ifuncs.close_ocb = &io_close;

	if (resmgr_attach(dpp, &resmgr_attr, device_name, _FTYPE_ANY, 0, &cfuncs,
		&ifuncs, &attr) == -1)
	{
		perror("error: resmgr_attach\n");
		exit(EXIT_FAILURE);
	}

	opened = 0;
	ctp = resmgr_context_alloc(dpp);
	while(1)
	{
		if ((ctp = resmgr_block(ctp)) == NULL)
		{
			perror("error: resmgr_block\n");
			exit(EXIT_FAILURE);
		}
		resmgr_handler(ctp);
	}
}
int io_open(resmgr_context_t *ctp, io_open_t *msg, 
	RESMGR_HANDLE_T *handle, void *extra)
{
	int ret;

	if (opened)
	{
		return(EBUSY);
	}
	
	ret = iofunc_open_default(ctp,msg,handle,extra);
	if (ret == EOK)
	{
		opened = TRUE;
	}
	return(ret);
}

singl_client.c:
int io_close(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
{
	int ret;

	opened = 0;

	return(iofunc_close_ocb_default(ctp,reserved,ocb));
}



#include <libc.h>
int main()
{
	FILE *fp;

	fp = fopen("/dev/mypgm","r");
	if (fp == NULL)
	{
		fprintf(stderr,"singl_client is already running\n");
		exit(-1);
	}
	fprintf(stderr,"I can run now\n");
	sleep(20);
	fprintf(stderr,"Done\n");
}


Thank you very much