[Mono-list] [PATCH] robust mono-handle-d?
Dennis Haney
davh@davh.dk
07 Jun 2002 16:35:52 +0200
--=-=-=
>>>>> "Dick" == Dick Porter <dick@ximian.com> writes:
Dick> On Thu, Jun 06, 2002 at 10:42:38PM +0200, Dennis Haney wrote:
>> This is primarily a documentation patch, but it also adds a single
>> error check (assert if unref is called with refcnt==0) and many
>> g_warning with a exit(-1) right after was changed to
>> g_critical. The states a daemon was running in was replaced by an
>> enum to make it more clean what is what.
Dick> Mostly OK. I've commented on some details below.
Dick> - Dick
>> + +The mono_handle_d is a process which takes care of the
>> (de)allocation +of scratch shared memory and filehandles and
>> refcounts of the +filehandles. It is designed to be run by a user
>> and to be fast, thus
Dick> Not just file handles, there are many sorts. Please change this
Dick> wording throughout the doc and the comments.
I believe that was the only place I was wrong. All other places I talk
about filehandles I refer to the filehandle of the client-sockets...
>> + +=head2 How to start the deamon
Dick> Please make sure you've spelled "daemon" correctly throughout
Dick> (including in typedefs :) )
;)
>> + +Deallocate a shared memory area, this must have been allocated
>> before +deallocating. A L<WapiHandleResponse> with
>> +.type=WapiHandleResponseType_Scratch Freewill be sent back (works
>> just
Dick> Some typos here
All I can see is the Free having a <sp> before instead of
after. Anymore?
>> Index: daemon-messages.c @@ -71,7 +71,11 @@ int ret;
>>
>> ret=recv (fd, req, sizeof(WapiHandleRequest), MSG_NOSIGNAL); + //we
>> cant check ret != sizeof(WapiHandleRequest) because its a + //union
Dick> Please replace the // comments with /* */
Done
>> ret=send (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL); -
>> if(ret==-1) { #ifdef DEBUG + if(ret==-1 || ret !=
>> sizeof(WapiHandleResponse)) {
Dick> I don't understand this bit. Earlier you said you can't use
Dick> sizeof on a union, but here you are doing it.
I now do the check both places. Point was that given a struct like:
struct p {
int a;
union b {
int c[1000];
int d;
}
}
If the client only fills out d, then it might only send a package
which is two ints long.
When the daemon itself sends a package we _know_ that we must send the
whole package or something is wrong.
>> Index: daemon-messages.h @@ -18,6 +18,7 @@
>> WapiHandleRequestType_Close, WapiHandleRequestType_Scratch,
>> WapiHandleRequestType_ScratchFree, + WapiHandleRequestType_Error, }
>> WapiHandleRequestType;
Dick> Please move the Error enum to the top of the list, to be
Dick> symmetrical with the responses.
Okay, this breaks binary compat though...
>> -static gpointer *handle_refs=NULL; +static guint32
>> **handle_refs=NULL;
Dick> Good catch.
>> static gboolean unref_handle (guint32 idx, guint32 handle) {
>> guint32 *open_handles=handle_refs[idx]; @@ -104,6 +137,8 @@
>> return(FALSE); }
>>
>> + g_assert(open_handles[handle] != 0); +
Dick> Shouldn't use assert in the daemon. Just g_warning and ignore
Dick> the request if the handle isn't open.
Better?
>> @@ -325,9 +433,19 @@ case WapiHandleRequestType_ScratchFree:
>> process_scratch_free (idx, req.u.scratch_free.idx); break; + case
>> WapiHandleRequestType_Error: /* Falltrough */ + default: + /*FIXME:
>> call rem_fd?*/ + break; }
Dick> I prefer to not use default in switch statements like this, so
Dick> the compiler will remind me when I've forgotten to add a case.
It is to catch faulty packages...
Dick> The rest is fine though.
Great[1] ;)
I just have one question about the daemon... Why does it exist? Isn't
it better performancewise[2] to just protect the shared area with a
mutex when allocation a new handle/shared mem segment or changing
refcnt? It will however be a less resilient to clients that crash (the
deamon cleans up ref'd handles if socket closes)
[1]
Attaching a new version per comments
[2]
Process of a client requesting a new handle:
client connects to shared segment (possibly starting a daemon)
client connects to daemon
...
client constructs a WapiHandleRequest package
client sends this package over a socket
process switch to the daemon
daemon scans sockets to find who is asking
daemon reads package
daemon allocates a new handle
daemon constructs a response package
daemon sends package
daemon listens to sockets again
process switch to the client
client reads package
client verifies package
With a lock:
client connects to shared segment (possibly init the locks)
...
client locks shared segment
client allocates a new handle
client unlocks shared segment
--
Dennis
use Inline C => qq{void p(char*g){
printf("Just Another %s Hacker\n",g);}};p("Perl");
--=-=-=
Content-Disposition: attachment; filename=mono_handle_d_diff1.diff
Index: daemon-messages.c
===================================================================
RCS file: /mono/mono/mono/io-layer/daemon-messages.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 daemon-messages.c
--- daemon-messages.c 31 May 2002 09:54:14 -0000 1.3
+++ daemon-messages.c 7 Jun 2002 13:55:20 -0000
@@ -25,7 +25,7 @@
/* Send request on fd, wait for response (called by applications, not
* the daemon)
-*/
+ */
void _wapi_daemon_request_response (int fd, WapiHandleRequest *req,
WapiHandleResponse *resp)
{
@@ -41,7 +41,7 @@
ret=send (fd, req, sizeof(WapiHandleRequest), MSG_NOSIGNAL);
if(ret!=sizeof(WapiHandleRequest)) {
if(errno==EPIPE) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
+ g_critical (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
exit (-1);
} else {
g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
@@ -53,7 +53,7 @@
ret=recv (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL);
if(ret==-1) {
if(errno==EPIPE) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
+ g_critical (G_GNUC_PRETTY_FUNCTION ": The handle daemon vanished!");
exit (-1);
} else {
g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
@@ -71,7 +71,9 @@
int ret;
ret=recv (fd, req, sizeof(WapiHandleRequest), MSG_NOSIGNAL);
- if(ret==-1) {
+ if(ret==-1 || ret != sizeof(WapiHandleRequest) {
+ /* make sure we dont do anything with this response */
+ req->type=WapiHandleRequestType_Error;
#ifdef DEBUG
g_warning (G_GNUC_PRETTY_FUNCTION ": Recv error: %s",
strerror (errno));
@@ -86,11 +88,11 @@
int ret;
ret=send (fd, resp, sizeof(WapiHandleResponse), MSG_NOSIGNAL);
- if(ret==-1) {
#ifdef DEBUG
+ if(ret==-1 || ret != sizeof(WapiHandleResponse)) {
g_warning (G_GNUC_PRETTY_FUNCTION ": Send error: %s",
strerror (errno));
-#endif
/* The next loop around poll() should tidy up */
}
+#endif
}
Index: daemon-messages.h
===================================================================
RCS file: /mono/mono/mono/io-layer/daemon-messages.h,v
retrieving revision 1.2
diff -u -b -B -r1.2 daemon-messages.h
--- daemon-messages.h 9 May 2002 13:10:18 -0000 1.2
+++ daemon-messages.h 7 Jun 2002 13:55:20 -0000
@@ -13,6 +13,7 @@
#include <mono/io-layer/wapi-private.h>
typedef enum {
+ WapiHandleRequestType_Error,
WapiHandleRequestType_New,
WapiHandleRequestType_Open,
WapiHandleRequestType_Close,
Index: daemon.c
===================================================================
RCS file: /mono/mono/mono/io-layer/daemon.c,v
retrieving revision 1.4
diff -u -b -B -r1.4 daemon.c
--- daemon.c 31 May 2002 10:41:30 -0000 1.4
+++ daemon.c 7 Jun 2002 13:55:20 -0000
@@ -27,9 +27,13 @@
#undef DEBUG
+/* Array to hold the filehandles we are currently polling */
static struct pollfd *pollfds=NULL;
+/* Keep track of the size and usage of pollfds */
static int nfds=0, maxfds=0;
-static gpointer *handle_refs=NULL;
+/* Array to keep track of arrays of handles that belong to a given client */
+static guint32 **handle_refs=NULL;
+/* The sockey which we listen to new connections on */
static int main_sock;
/* Deletes the shared memory segment. If we're exiting on error,
@@ -40,12 +44,23 @@
_wapi_shm_destroy ();
}
+/*
+ * signal_handler:
+ * @unused: unused
+ *
+ * Called if daemon receives a SIGTERM or SIGINT
+ */
static void signal_handler (int unused)
{
cleanup ();
exit (-1);
}
+/*
+ * startup:
+ *
+ * Bind signals and attach to shared memory
+ */
static void startup (void)
{
struct sigaction sa;
@@ -76,6 +91,15 @@
time (NULL));
}
+
+/*
+ * ref_handle:
+ * @idx: idx into pollfds
+ * @handle: handle to inc refcnt
+ *
+ * Increase ref count of handle for idx's filehandle and the
+ * shm. Handle 0 is ignored.
+ */
static void ref_handle (guint32 idx, guint32 handle)
{
guint32 *open_handles=handle_refs[idx];
@@ -95,6 +119,15 @@
#endif
}
+/*
+ * unref_handle:
+ * @idx: idx into pollfds
+ * @handle: handle to inc refcnt
+ *
+ * Decrease ref count of handle for idx's filehandle and the shm. If
+ * global ref count reaches 0 it is free'ed. Return TRUE if the local
+ * ref count is 0. Handle 0 is ignored.
+ */
static gboolean unref_handle (guint32 idx, guint32 handle)
{
guint32 *open_handles=handle_refs[idx];
@@ -104,6 +137,13 @@
return(FALSE);
}
+ if (open_handles[handle] == 0) {
+ g_warning(G_GNUC_PRETTY_FUNCTION
+ ": unref on %d called when ref was already 0",
+ handle);
+ return TRUE;
+ }
+
_wapi_shared_data->handles[handle].ref--;
open_handles[handle]--;
@@ -120,9 +160,7 @@
}
if(_wapi_shared_data->handles[handle].ref==0) {
- if (open_handles[handle]!=0) {
- g_warning (G_GNUC_PRETTY_FUNCTION ": per-process open_handles mismatch, set to %d, should be 0", open_handles[handle]);
- }
+ g_assert(open_handles[handle] == 0);
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": Destroying handle 0x%x",
@@ -140,13 +178,21 @@
return(destroy);
}
+/*
+ * add_fd:
+ * @fd: Filehandle to add
+ *
+ * Add fd to the pollfds array, expand if necessary
+ */
static void add_fd(int fd)
{
if(nfds==maxfds) {
/* extend the array */
maxfds+=10;
+ /* no need to memset the extra memory, we init it
+ * before use anyway */
pollfds=g_renew (struct pollfd, pollfds, maxfds);
- handle_refs=g_renew (gpointer, handle_refs, maxfds);
+ handle_refs=g_renew (guint32*, handle_refs, maxfds);
}
pollfds[nfds].fd=fd;
@@ -158,6 +204,14 @@
nfds++;
}
+/*
+ * rem_fd:
+ * @idx: idx into pollfds to remove
+ *
+ * Close filehandle and remove it from the pollfds array. Closes all
+ * handles that it may have open. If only main_sock is open, the daemon
+ * is shut down.
+ */
static void rem_fd(int idx)
{
guint32 *open_handles=handle_refs[idx], handle_count;
@@ -205,12 +259,28 @@
}
}
+
+/*
+ * send_reply:
+ * @idx: idx into pollfds.
+ * @rest: Package to send
+ *
+ * Send a package to a client
+ */
static void send_reply (guint32 idx, WapiHandleResponse *resp)
{
/* send message */
_wapi_daemon_response (pollfds[idx].fd, resp);
}
+/*
+ * process_new:
+ * @idx: idx into pollfds.
+ * @type: type to init handle to
+ *
+ * Find a free handle and initialize it to 'type', increase refcnt and
+ * send back a reply to the client.
+ */
static void process_new (guint32 idx, WapiHandleType type)
{
guint32 handle;
@@ -231,6 +301,14 @@
send_reply (idx, &resp);
}
+/*
+ * process_open:
+ * @idx: idx into pollfds.
+ * @handle: handle no.
+ *
+ * Increase refcnt on a previously created handle and send back a
+ * response to the client.
+ */
static void process_open (guint32 idx, guint32 handle)
{
WapiHandleResponse resp;
@@ -259,6 +337,14 @@
send_reply (idx, &resp);
}
+/*
+ * process_close:
+ * @idx: idx into pollfds.
+ * @handle: handle no.
+ *
+ * Decrease refcnt on a previously created handle and send back a
+ * response to the client with notice of it being destroyed.
+ */
static void process_close (guint32 idx, guint32 handle)
{
WapiHandleResponse resp;
@@ -273,6 +359,13 @@
send_reply (idx, &resp);
}
+/*
+ * process_scratch:
+ * @idx: idx into pollfds.
+ * @length: allocate this much scratch space
+ *
+ * Allocate some scratch space and send a reply to the client.
+ */
static void process_scratch (guint32 idx, guint32 length)
{
WapiHandleResponse resp;
@@ -288,6 +381,13 @@
send_reply (idx, &resp);
}
+/*
+ * process_scratch_free:
+ * @idx: idx into pollfds.
+ * @scratch_idx: deallocate this scratch space
+ *
+ * Deallocate scratch space and send a reply to the client.
+ */
static void process_scratch_free (guint32 idx, guint32 scratch_idx)
{
WapiHandleResponse resp;
@@ -303,6 +403,13 @@
send_reply (idx, &resp);
}
+/*
+ * read_message:
+ * @idx: idx into pollfds.
+ *
+ * Read a message (A WapiHandleRequest) from a client and dispatch
+ * whatever it wants to the process_* calls.
+ */
static void read_message (guint32 idx)
{
WapiHandleRequest req;
@@ -314,9 +421,15 @@
process_new (idx, req.u.new.type);
break;
case WapiHandleRequestType_Open:
+#ifdef DEBUG
+ g_assert(req.u.open.handle < _WAPI_MAX_HANDLES);
+#endif
process_open (idx, req.u.open.handle);
break;
case WapiHandleRequestType_Close:
+#ifdef DEBUG
+ g_assert(req.u.close.handle < _WAPI_MAX_HANDLES);
+#endif
process_close (idx, req.u.close.handle);
break;
case WapiHandleRequestType_Scratch:
@@ -325,9 +438,19 @@
case WapiHandleRequestType_ScratchFree:
process_scratch_free (idx, req.u.scratch_free.idx);
break;
+ case WapiHandleRequestType_Error: /* Falltrough */
+ default: /* Catch faulty packages */
+ /*FIXME: call rem_fd?*/
+ break;
}
}
+/*
+ * main:
+ *
+ * Open socket, create shared mem segment and begin listening for
+ * clients.
+ */
int main(int argc, char **argv)
{
struct sockaddr_un main_socket_address;
@@ -347,8 +470,8 @@
ret=bind(main_sock, (struct sockaddr *)&main_socket_address,
sizeof(struct sockaddr_un));
if(ret==-1) {
- g_warning ("bind failed: %s", strerror (errno));
- _wapi_shared_data->daemon_running=2;
+ g_critical ("bind failed: %s", strerror (errno));
+ _wapi_shared_data->daemon_running=DAEMON_DIED_AT_STARTUP;
exit(-1);
}
@@ -358,8 +481,8 @@
ret=listen(main_sock, 5);
if(ret==-1) {
- g_warning ("listen failed: %s", strerror (errno));
- _wapi_shared_data->daemon_running=2;
+ g_critical ("listen failed: %s", strerror (errno));
+ _wapi_shared_data->daemon_running=DAEMON_DIED_AT_STARTUP;
exit(-1);
}
@@ -373,7 +496,7 @@
* ready. From now on, it's up to us to delete the shared
* memory segment when appropriate.
*/
- _wapi_shared_data->daemon_running=1;
+ _wapi_shared_data->daemon_running=DAEMON_RUNNING;
while(TRUE) {
int i;
@@ -385,21 +508,29 @@
/* Block until something happens */
ret=poll(pollfds, nfds, -1);
if(ret==-1) {
- g_message ("poll error: %s", strerror (errno));
+ g_critical ("poll error: %s", strerror (errno));
cleanup ();
exit(-1);
}
for(i=0; i<nfds; i++) {
- if(((pollfds[i].revents&POLLHUP)==POLLHUP) ||
- ((pollfds[i].revents&POLLERR)==POLLERR) ||
- ((pollfds[i].revents&POLLNVAL)==POLLNVAL)) {
+ if(((pollfds[i].revents & POLLHUP) == POLLHUP) ||
+ ((pollfds[i].revents & POLLERR) == POLLERR) ||
+ ((pollfds[i].revents & POLLNVAL) == POLLNVAL)) {
#ifdef DEBUG
g_message ("fd[%d] %d error", i,
pollfds[i].fd);
#endif
rem_fd(i);
} else if((pollfds[i].revents&POLLIN)==POLLIN) {
+ /* If a client is connecting, accept
+ * it and begin listening to that
+ * socket too otherwise it must be a
+ * client we already have that wants
+ * something
+ */
+
+ /* FIXME: Isn't this only true for i==0??? */
if(pollfds[i].fd==main_sock) {
int newsock;
struct sockaddr addr;
@@ -407,7 +538,7 @@
newsock=accept(main_sock, &addr,
&addrlen);
if(newsock==-1) {
- g_message("accept error: %s",
+ g_critical("accept error: %s",
strerror (errno));
cleanup ();
exit(-1);
Index: handles.c
===================================================================
RCS file: /mono/mono/mono/io-layer/handles.c,v
retrieving revision 1.12
diff -u -b -B -r1.12 handles.c
--- handles.c 31 May 2002 10:41:30 -0000 1.12
+++ handles.c 7 Jun 2002 13:55:20 -0000
@@ -136,6 +136,13 @@
thread_handle=_wapi_handle_new (WAPI_HANDLE_THREAD);
}
+/*
+ * _wapi_handle_new_internal:
+ * @type: Init handle to this type
+ *
+ * Search for a free handle and initialize it. Return the handle on
+ * succes and 0 on failure.
+ */
guint32 _wapi_handle_new_internal (WapiHandleType type)
{
guint32 i;
@@ -150,7 +157,7 @@
struct _WapiHandleShared *shared=&_wapi_shared_data->handles[i];
if(shared->type==WAPI_HANDLE_UNUSED) {
- last=i;
+ last=i+1;
shared->type=type;
shared->signalled=FALSE;
mono_mutex_init (&_wapi_shared_data->handles[i].signal_mutex, &mutex_shared_attr);
@@ -350,6 +357,13 @@
#define HDRSIZE sizeof(struct _WapiScratchHeader)
+/*
+ * _wapi_handle_scratch_store_internal:
+ * @bytes: Allocate no. bytes
+ *
+ * Like malloc(3) except its for the shared memory segment's scratch
+ * part. Memory block returned is zeroed out.
+ */
guint32 _wapi_handle_scratch_store_internal (guint32 bytes)
{
guint32 idx=0, last_idx=0;
@@ -400,6 +414,10 @@
g_message (G_GNUC_PRETTY_FUNCTION ": new header at %d, length %d", idx+bytes, hdr->length);
#endif
+ /*
+ * It was memset(0..) when free/made so no need to do it here
+ */
+
return(idx);
} else if(hdr->flags & WAPI_SHM_SCRATCH_FREE &&
last_was_free == FALSE) {
@@ -516,6 +534,13 @@
return(str);
}
+/*
+ * _wapi_handle_scratch_delete_internal:
+ * @idx: Index to free block
+ *
+ * Like free(3) except its for the shared memory segment's scratch
+ * part.
+ */
void _wapi_handle_scratch_delete_internal (guint32 idx)
{
struct _WapiScratchHeader *hdr;
Index: shared.c
===================================================================
RCS file: /mono/mono/mono/io-layer/shared.c,v
retrieving revision 1.4
diff -u -b -B -r1.4 shared.c
--- shared.c 9 May 2002 13:10:18 -0000 1.4
+++ shared.c 7 Jun 2002 13:55:20 -0000
@@ -56,6 +56,17 @@
#undef DEBUG
+/*
+ * _wapi_shm_attach:
+ * @daemon: Is it the daemon trying to attach to the segment
+ * @success: Was it a success
+ * @shm_id: The ID of the segment created/attached to
+ *
+ * Attach to the shared memory segment or create it if it did not
+ * exist. If it was created and daemon was FALSE a new daemon is
+ * forked into existence. Returns the memory area the segment was
+ * attached to.
+ */
gpointer _wapi_shm_attach (gboolean daemon, gboolean *success, int *shm_id)
{
gpointer shm_seg;
@@ -99,7 +110,7 @@
*/
} else {
/* Some error other than EEXIST */
- g_message (G_GNUC_PRETTY_FUNCTION ": shmget error: %s",
+ g_critical (G_GNUC_PRETTY_FUNCTION ": shmget error: %s",
strerror (errno));
exit (-1);
}
@@ -110,7 +121,7 @@
*/
shm_seg=shmat (*shm_id, NULL, 0);
if(shm_seg==(gpointer)-1) {
- g_message (G_GNUC_PRETTY_FUNCTION ": shmat error: %s",
+ g_critical (G_GNUC_PRETTY_FUNCTION ": shmat error: %s",
strerror (errno));
if(fork_daemon==TRUE) {
_wapi_shm_destroy ();
@@ -131,7 +142,7 @@
pid=fork ();
if(pid==-1) {
- g_message (G_GNUC_PRETTY_FUNCTION ": fork error: %s",
+ g_critical (G_GNUC_PRETTY_FUNCTION ": fork error: %s",
strerror (errno));
_wapi_shm_destroy ();
exit (-1);
@@ -140,9 +151,9 @@
setsid ();
execl (MONO_BINDIR "/mono-handle-d", "mono-handle-d",
NULL);
- g_warning (": exec of %s/mono-handle-d failed: %s",
+ g_critical (": exec of %s/mono-handle-d failed: %s",
MONO_BINDIR, strerror (errno));
- data->daemon_running=2;
+ data->daemon_running=DAEMON_DIED_AT_STARTUP;
exit (-1);
}
/* parent carries on */
@@ -150,8 +161,9 @@
/* Do some sanity checking on the shared memory we
* attached
*/
- if(!(data->daemon_running==0 || data->daemon_running==1 ||
- data->daemon_running==2) ||
+ if(!(data->daemon_running==DAEMON_STARTING ||
+ data->daemon_running==DAEMON_RUNNING ||
+ data->daemon_running==DAEMON_DIED_AT_STARTUP) ||
(strncmp (data->daemon+1, "mono-handle-daemon-", 19)!=0)) {
g_warning ("Shared memory sanity check failed.");
*success=FALSE;
@@ -159,7 +171,7 @@
}
}
- for(tries=0; data->daemon_running==0 && tries < 100; tries++) {
+ for(tries=0; data->daemon_running==DAEMON_STARTING && tries < 100; tries++) {
/* wait for the daemon to sort itself out. To be
* completely safe, we should have a timeout before
* giving up.
@@ -171,7 +183,7 @@
nanosleep (&sleepytime, NULL);
}
- if(tries==100 && data->daemon_running==0) {
+ if(tries==100 && data->daemon_running==DAEMON_STARTING) {
/* Daemon didnt get going */
if(fork_daemon==TRUE) {
_wapi_shm_destroy ();
@@ -181,7 +193,7 @@
return(NULL);
}
- if(data->daemon_running==2) {
+ if(data->daemon_running==DAEMON_DIED_AT_STARTUP) {
/* Oh dear, the daemon had an error starting up */
if(fork_daemon==TRUE) {
_wapi_shm_destroy ();
Index: wapi-private.h
===================================================================
RCS file: /mono/mono/mono/io-layer/wapi-private.h,v
retrieving revision 1.12
diff -u -b -B -r1.12 wapi-private.h
--- wapi-private.h 9 May 2002 13:10:19 -0000 1.12
+++ wapi-private.h 7 Jun 2002 13:55:20 -0000
@@ -95,6 +95,12 @@
#define _WAPI_MAX_HANDLES 4096
#define _WAPI_HANDLE_INVALID (gpointer)-1
+typedef enum {
+ DAEMON_STARTING = 0,
+ DAEMON_RUNNING = 1,
+ DAEMON_DIED_AT_STARTUP = 2,
+} _wapi_daemon_status;
+
/*
* This is the layout of the shared memory segment
*/
@@ -104,7 +110,7 @@
* header file
*/
guchar daemon[108];
- guint32 daemon_running;
+ _wapi_daemon_status daemon_running;
#ifdef _POSIX_THREAD_PROCESS_SHARED
mono_mutex_t signal_mutex;
--- /dev/null Thu Jan 1 01:00:00 1970
+++ docs/mono_handle_d Fri Jun 7 15:19:57 2002
@@ -0,0 +1,80 @@
+=pod
+
+=head1 Internal design document for the mono_handle_d
+
+This document is designed to hold the design of the mono_handle_d and
+not as an api reference.
+
+=head2 Primary goal and purpose
+
+The mono_handle_d is a process which takes care of the (de)allocation
+of scratch shared memory and handles (of files, threads, mutexes,
+sockets etc. see L<WapiHandleType>) and refcounts of the
+filehandles. It is designed to be run by a user and to be fast, thus
+minimal error checking on input is done and will most likely crash if
+given a faulty package. No effort has been, or should be, made to have
+the daemon talking to machine of different endianness/size of int.
+
+=head2 How to start the daemon
+
+To start the daemon you either run the mono_handle_d executable or try
+to attach to the shared memory segment via L<_wapi_shm_attach> which
+will start a daemon if one does not exist.
+
+=head1 Internal details
+
+The daemon works by opening a socket and listening to clients. These
+clients send packages over the socket complying to L<struct
+WapiHandleRequest>.
+
+=head2 Possible requests
+
+=over
+
+=item WapiHandleRequest_New
+
+Find a handle in the shared memory segment that is free and allocate
+it to the specified type. To destroy use
+L</WapiHandleRequest_Close>. A L<WapiHandleResponse> with
+.type=WapiHandleResponseType_New will be sent back with .u.new.handle
+set to the handle that was allocated. .u.new.type is the type that was
+requested.
+
+=item WapiHandleRequestType_Open
+
+Increase the ref count of an already created handle. A
+L<WapiHandleResponse> with .type=WapiHandleResponseType_Open will be sent
+back with .u.new.handle set to the handle, .u.new.type is set to the
+type of handle this is.
+
+=item WapiHandleRequestType_Close
+
+Decrease the ref count of an already created handle. A
+L<WapiHandleResponse> with .type=WapiHandleResponseType_Close will be
+sent back with .u.close.destroy set to TRUE if ref count for this
+client reached 0.
+
+=item WapiHandleRequestType_Scratch
+
+Allocate a shared memory area of size .u.scratch.length in bytes. A
+L<WapiHandleResponse> with .type=WapiHandleResponseType_Scratch will be
+sent back with .u.scratch.idx set to the index into the shared
+memory's scratch area where to memory begins. (works just like
+malloc(3))
+
+=item WapiHandleRequestType_Scratch
+
+Deallocate a shared memory area, this must have been allocated before
+deallocating. A L<WapiHandleResponse> with
+.type=WapiHandleResponseType_Scratch Freewill be sent back (works just
+like free(3))
+
+=back
+
+=head1 Authors
+
+Documentaion: Dennis Haney
+
+Implementation: Dick Porter
+
+=cut
--- /dev/null Thu Jan 1 01:00:00 1970
+++ docs/.cvsignore Sun Jun 2 00:00:05 2002
@@ -0,0 +1 @@
+Makefile Makefile.in
--=-=-=--