Re: Control lifecycle thoughts ...



Hi Michael,

On Wed, 24 Oct 2001, Michael Meeks wrote:

>
> Hi Darin,
>
> 	I've been considering the lifecycle issues - and coming up with an
> improved method for Gnome 2.0; and I'd greatly appreciate your comments on
> my thoughts, in libbonoboui/doc/control.txt

	This all looks fine to me except ...

> * Creation interaction (A)
>
> 	1. Control creation
> 	2. Passes it's reference
>         3.                       _control_frame_new
> 	4.			 creates ControlFrame
> 	5.			 creates Socket
> 	6.			 _control_frame_bind_to_control
> 	7.			 takes a B. Control ref.
> 	8.			 Control->setFrame
> 	9. takes a C. control_frame ref
	          ^^^

	This should be a B. ref yes ?

> * CORBA connection 'broken' signal
>
> 	This signal is totaly unaffected by CORBA reference counting,
> and will happily leave an object with a broken connection - but we'll
> get a nice signal.
>
> 	We only get this signal using Unix Domain Sockets - FIXME,
> check whether this is at all portable - are we notified by poll of
> broken connections on Solaris etc. or do we need periodic ping
> evilness there; if so - can we use some other mechanism.

	In ORBit2 I made the assumption that if there has been a
passive close on your socket, you get a POLLIN from poll and EOF when
you read the socket.

	I've just hacked up some code to test this assumption - it
works, for UDS and IP on both Solaris and Linux. The code is attached.

	Note that POLLHUP isn't useful to us because, on a passive
close, we only get for UDS and only on Linux.

Good Luck,
Mark.
/*
 * Socket hangup test.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Author: Mark McLoughlin <mark skynet ie>
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <netinet/in.h>

#define PORTNUM  3030
#define UDS_PATH "/tmp/uds-0001"

typedef enum {
	TEST_IP4,
	TEST_UDS
} TestCase;

void try_read (int fd)
{
	char buf [10];
	int  n;

	fprintf (stderr, "Trying a read.\n");

	n = read (fd, buf, 10);
	if (!n)
		fprintf (stderr, "EOF. Connection dead.\n");
	else
		fprintf (stderr, "Doh. Connection okay.\n");
}

void server (TestCase test_case)
{
	struct sockaddr_in  servaddr_in;
	struct sockaddr_un  servaddr_un;
	struct sockaddr    *servaddr;
	struct pollfd       fds[1];
	int                 listenfd;
	int                 n;
	int                 servaddr_len;

	switch (test_case) {
	case TEST_IP4:
		memset (&servaddr_in, 0, sizeof (struct sockaddr_in));

		servaddr_in.sin_family      = AF_INET;
		servaddr_in.sin_port        = htons (PORTNUM);
		servaddr_in.sin_addr.s_addr = htonl (INADDR_ANY);

		servaddr     = (struct sockaddr *)&servaddr_in;
		servaddr_len = sizeof (struct sockaddr_in);

		break;
	case TEST_UDS:
		memset (&servaddr_un, 0, sizeof (struct sockaddr_un));

		servaddr_un.sun_family      = AF_UNIX;

		strcpy (servaddr_un.sun_path, UDS_PATH);

		servaddr     = (struct sockaddr *)&servaddr_un;
		servaddr_len = sizeof (struct sockaddr_un) -
			       sizeof (servaddr_un.sun_path) +
			       strlen (UDS_PATH);
		break;
	default:
		break;
	}

	listenfd = socket (servaddr->sa_family, SOCK_STREAM, 0);
	if (listenfd == -1)
		return;

	bind (listenfd, servaddr, servaddr_len);

	n = listen (listenfd, 5);
	if (n == -1)
		return;

	fds [0].fd = accept (listenfd, (struct sockaddr *)NULL, NULL);
	if (fds [0].fd == -1)
		return;

	fds [0].events = POLLIN|POLLPRI;

	n = poll (fds, 1, -1);
	if (n != 1)
		return;

	if (fds [0].revents | POLLIN) {
		fprintf (stderr, "poll returned POLLIN.\n");
		try_read (fds [0].fd);
	}
	else
		fprintf (stderr, "poll failed to return POLLIN.\n");
}

void client (TestCase test_case)
{
	struct sockaddr_in  servaddr_in;
	struct sockaddr_un  servaddr_un;
	struct sockaddr    *servaddr;
	int                 fd;
	int                 n;
	int                 servaddr_len;

	switch (test_case) {
	case TEST_IP4:
		memset (&servaddr_in, 0, sizeof (struct sockaddr_in));

		servaddr_in.sin_family      = AF_INET;
		servaddr_in.sin_port        = htons (PORTNUM);
		servaddr_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

		servaddr     = (struct sockaddr *)&servaddr_in;
		servaddr_len = sizeof (struct sockaddr_in);

		break;
	case TEST_UDS:
		memset (&servaddr_un, 0, sizeof (struct sockaddr_un));

		servaddr_un.sun_family      = AF_UNIX;

		strcpy (servaddr_un.sun_path, UDS_PATH);

		servaddr     = (struct sockaddr *)&servaddr_un;
		servaddr_len = sizeof (struct sockaddr_un) -
			       sizeof (servaddr_un.sun_path) +
			       strlen (UDS_PATH);
		break;
	default:
		break;
	}


	fd = socket (servaddr->sa_family, SOCK_STREAM, 0);
	if (fd == -1)
		return;

	n = connect (fd, servaddr, servaddr_len);
	if (n == -1)
		return;

	*((char *)NULL) = 0;  /* dump core */
}

int main (int argc, char **argv)
{
	pid_t pid;

	fprintf (stderr, "IP4 test.\n");

	if (pid = fork ())
		server (TEST_IP4);
	else {
		sleep (1);
		client (TEST_IP4);
		return 0;
	}

	waitpid (pid, NULL, 0);

	fprintf (stderr, "UDS test.\n");

	unlink (UDS_PATH);

	if (pid = fork ())
		server (TEST_UDS);
	else {
		sleep (1);
		client (TEST_UDS);
		return 0;
	}

	waitpid (pid, NULL, 0);

	return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]