From d4de3d0a45da6745dccf6d561fdaffe27e0f0749 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 9 Sep 2002 04:25:51 +0000 Subject: [PATCH] - new function in WINGs: WMSetConnectionShutdownOnClose() - new callback in the ConnectionDelegate structure: canResumeSending - replaced setpgid() with setsid() when starting kids, to allow them to survive if wmaker (the parent) dies. - a few cleanups. --- WINGs/ChangeLog | 7 ++++++ WINGs/Examples/connect.c | 1 + WINGs/Examples/server.c | 1 + WINGs/NEWS | 52 +++++++++++++++++++++++++++++++++++++++++++ WINGs/WINGs/WUtil.h | 7 ++++-- WINGs/connection.c | 57 +++++++++++++++++++++++++++++++++++------------- WINGs/handlers.c | 1 - WINGs/wutil.c | 2 +- configure.ac | 4 ++-- src/dock.c | 4 ++-- src/main.c | 4 ++-- 11 files changed, 115 insertions(+), 25 deletions(-) diff --git a/WINGs/ChangeLog b/WINGs/ChangeLog index e9ffea2c..5d66b81f 100644 --- a/WINGs/ChangeLog +++ b/WINGs/ChangeLog @@ -1,3 +1,10 @@ +Changes since wmaker 0.80.1: +............................ + +- added WMSetConnectionShutdownOnClose() +- added an extra member to the ConnectionDelegate: canResumeSending + see NEWS for details. + Changes since wmaker 0.80.0: ............................ diff --git a/WINGs/Examples/connect.c b/WINGs/Examples/connect.c index 55d8b76e..be753fb8 100644 --- a/WINGs/Examples/connect.c +++ b/WINGs/Examples/connect.c @@ -28,6 +28,7 @@ static void didInitialize(ConnectionDelegate *self, WMConnection *cPtr); static ConnectionDelegate socketDelegate = { NULL, /* data */ + NULL, /* canResumeSending */ NULL, /* didCatchException */ connectionDidDie, /* didDie */ didInitialize, /* didInitialize */ diff --git a/WINGs/Examples/server.c b/WINGs/Examples/server.c index d421e114..502febcd 100644 --- a/WINGs/Examples/server.c +++ b/WINGs/Examples/server.c @@ -42,6 +42,7 @@ static WMConnection *serverPtr = NULL; static ConnectionDelegate socketDelegate = { NULL, /* client data */ + NULL, /* canResumeSending */ NULL, /* didCatchException */ connectionDidDie, /* didDie */ NULL, /* didInitialize */ diff --git a/WINGs/NEWS b/WINGs/NEWS index 02403e26..0f6d39d1 100644 --- a/WINGs/NEWS +++ b/WINGs/NEWS @@ -1,3 +1,55 @@ +*** Mon Sep 09 06:58:30 EEST 2002 - Dan + +New delegate for the WMConnection class +--------------------------------------- + +ConnectionDelegate structure has a new member: canResumeSending. +The purpose of this callback is to notify you that you can resume sending +data over a WMConnection. +It works in the following manner: + +WMSendConnectionData() can return 3 values: -1, 0, 1 + +-1 - means that the connection has died. you should stop sending data and + close the connection ASAP. + 1 - means that the data was succesfully sent + 0 - means that the data (or part of it) was not sent. however, it was saved + in a queue and the library will try to send it later when possible. + +if the return value is 1, you can continue to send the next message, and so +on, until the return value of such a send call will be 0. +In this case you can continue sending, however, the data will not be sent +over the connection because the operating system cannot accept any more data +for the moment. Instead it will be queued inside the library, making your +program's memory footprint increase. If the ammount of data you need to +send is limited and not too big, this shouldn't be a problem, because your +data will be queued and sent when the operating system will notify the +library that sending is possible again. +If this is the case you can just ignore the output of WMSendConnectionData() +and not set a callback for canResumeSending. + +However, if the ammount of data you have to send is undetermined and you +also want to keep a small memory footprint for your program (so that it +won't grow until it uses all your available memory ;) ), you will have to +stop sending data over the connection as soon as WMSendConnectionData() +returns with 0. Then you should somehow mark this situation in your program +to avoid it trying to send anymore data until notified that it can resume. +(You should have also set a canResumeSending callback when you initialized +your WMConnection object because else you cannot be notified when to resume.) + +Now, when you receive such a 0 from the send operation, your last sent data +is put in a queue inside the library. At a later time when the operating +system notifies the library that sending is possible again, the library will +resume to send the data that is saved in the queue. After it will be able to +send all the data in the queue, the canResumeSending callback will be +called, letting you know that not only you can resume sending because the +operating system is again able to send data, but also that the queue was +completely flushed. + +From the canResumeSending callback, you should again update the status of +your program marking that it can send again, and then resume sending the +data from where you were left. + *** Thu Oct 04 06:00:09 EEST 2001 -Dan diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index f8865752..98ea6aad 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -184,8 +184,9 @@ typedef struct { typedef struct ConnectionDelegate { void *data; - void (*didCatchException)(struct ConnectionDelegate *self, - WMConnection *cPtr); + void (*canResumeSending)(struct ConnectionDelegate *self, WMConnection *cPtr); + + void (*didCatchException)(struct ConnectionDelegate *self, WMConnection *cPtr); void (*didDie)(struct ConnectionDelegate *self, WMConnection *cPtr); @@ -977,6 +978,8 @@ Bool WMSetConnectionNonBlocking(WMConnection *cPtr, Bool flag); Bool WMSetConnectionCloseOnExec(WMConnection *cPtr, Bool flag); +void WMSetConnectionShutdownOnClose(WMConnection *cPtr, Bool flag); + void* WMGetConnectionClientData(WMConnection *cPtr); void WMSetConnectionClientData(WMConnection *cPtr, void *data); diff --git a/WINGs/connection.c b/WINGs/connection.c index ac82f80b..94878e7d 100644 --- a/WINGs/connection.c +++ b/WINGs/connection.c @@ -1,8 +1,8 @@ /* * WINGs WMConnection function library - * + * * Copyright (c) 1999-2002 Dan Pascu - * + * * 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 of the License, or @@ -121,6 +121,7 @@ typedef struct W_Connection { char *protocol; Bool closeOnRelease; + Bool shutdownOnClose; Bool wasNonBlocking; Bool isNonBlocking; @@ -192,9 +193,10 @@ inputHandler(int fd, int mask, void *clientData) return; if ((mask & WIWriteMask)) { + int result; + if (cPtr->state == WCInProgress) { Bool failed; - int result; int len = sizeof(result); WCErrorCode = 0; @@ -228,7 +230,10 @@ inputHandler(int fd, int mask, void *clientData) if (failed) return; } else if (cPtr->state == WCConnected) { - WMFlushConnection(cPtr); + result = WMFlushConnection(cPtr); + if (result>0 && cPtr->delegate && cPtr->delegate->canResumeSending) { + (*cPtr->delegate->canResumeSending)(cPtr->delegate, cPtr); + } } } @@ -376,6 +381,7 @@ createConnectionWithSocket(int sock, Bool closeOnRelease) cPtr->sendTimeout.timeout = DefaultTimeout; cPtr->sendTimeout.handler = NULL; cPtr->closeOnRelease = closeOnRelease; + cPtr->shutdownOnClose = 1; cPtr->outputQueue = WMCreateArrayWithDestructor(16, (WMFreeDataProc*)WMReleaseData); cPtr->state = WCNotConnected; @@ -412,7 +418,7 @@ WMCreateConnectionWithSocket(int sock, Bool closeOnRelease) /* some way to find out if it is connected, and binded. can't find if it listens though!!! - */ + */ size = sizeof(clientname); n = getpeername(sock, (struct sockaddr*) &clientname, &size); @@ -627,7 +633,9 @@ void WMDestroyConnection(WMConnection *cPtr) { if (cPtr->closeOnRelease && cPtr->sock>=0) { - shutdown(cPtr->sock, SHUT_RDWR); + if (cPtr->shutdownOnClose) { + shutdown(cPtr->sock, SHUT_RDWR); + } close(cPtr->sock); } @@ -648,7 +656,9 @@ void WMCloseConnection(WMConnection *cPtr) { if (cPtr->sock>=0) { - shutdown(cPtr->sock, SHUT_RDWR); + if (cPtr->shutdownOnClose) { + shutdown(cPtr->sock, SHUT_RDWR); + } close(cPtr->sock); cPtr->sock = -1; } @@ -743,10 +753,18 @@ WMEnqueueConnectionData(WMConnection *cPtr, WMData *data) } +/* + * Return value: + * -1 - not connected or connection died while sending + * 0 - couldn't send the data (or part of it). data is saved in a queue + * and will be sent when possible. after it is sent the canResumeSending + * callback will be called. + * 1 - data was succesfully sent + */ int WMSendConnectionData(WMConnection *cPtr, WMData *data) { - int bytes, pos, len, totalTransfer; + int bytes, pos, len; TimeoutData *tPtr = &cPtr->sendTimeout; const unsigned char *dataBytes; @@ -767,8 +785,6 @@ WMSendConnectionData(WMConnection *cPtr, WMData *data) return 0; } - totalTransfer = 0; - while (WMGetArrayItemCount(cPtr->outputQueue) > 0) { data = WMGetFromArray(cPtr->outputQueue, 0); dataBytes = (const unsigned char *)WMDataBytes(data); @@ -793,7 +809,7 @@ WMSendConnectionData(WMConnection *cPtr, WMData *data) WMAddInputHandler(cPtr->sock, WIWriteMask, inputHandler, cPtr); } - return totalTransfer; + return 0; default: WCErrorCode = errno; cPtr->state = WCDied; @@ -804,7 +820,6 @@ WMSendConnectionData(WMConnection *cPtr, WMData *data) } } pos += bytes; - totalTransfer += bytes; } WMDeleteFromArray(cPtr->outputQueue, 0); cPtr->bufPos = 0; @@ -812,13 +827,18 @@ WMSendConnectionData(WMConnection *cPtr, WMData *data) WMDeleteTimerHandler(tPtr->handler); tPtr->handler = NULL; } - if (cPtr->handler.write) { + /*if (cPtr->handler.write) { WMDeleteInputHandler(cPtr->handler.write); cPtr->handler.write = NULL; - } + }*/ } - return totalTransfer; + if (cPtr->handler.write) { + WMDeleteInputHandler(cPtr->handler.write); + cPtr->handler.write = NULL; + } + + return 1; } @@ -952,6 +972,13 @@ WMSetConnectionCloseOnExec(WMConnection *cPtr, Bool flag) } +void +WMSetConnectionShutdownOnClose(WMConnection *cPtr, Bool flag) +{ + cPtr->shutdownOnClose = ((flag==0) ? 0 : 1); +} + + void* WMGetConnectionClientData(WMConnection *cPtr) { diff --git a/WINGs/handlers.c b/WINGs/handlers.c index eb77308a..e081043c 100644 --- a/WINGs/handlers.c +++ b/WINGs/handlers.c @@ -603,7 +603,6 @@ W_HandleInputEvents(Bool waitForInput, int inputfd) W_FlushASAPNotificationQueue(); - /* --oldway-- return ((inputfd < 0) ? (count > 0) : FD_ISSET(inputfd, &rset));*/ return (count > 0); #else /* not HAVE_SELECT, not HAVE_POLL */ Neither select nor poll. You lose. diff --git a/WINGs/wutil.c b/WINGs/wutil.c index 814d59a1..f28c459c 100644 --- a/WINGs/wutil.c +++ b/WINGs/wutil.c @@ -14,7 +14,7 @@ WHandleEvents() W_CheckTimerHandlers(); /* Do idle and timer stuff while there are no input events */ - /* Do not wait for input here. just peek to se if input is available */ + /* Do not wait for input here. just peek to see if input is available */ while (!W_HandleInputEvents(False, -1) && W_CheckIdleHandlers()) { /* dispatch timer events */ W_CheckTimerHandlers(); diff --git a/configure.ac b/configure.ac index 687931a4..c2bfcd43 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ AC_INIT(src/WindowMaker.h) -AM_INIT_AUTOMAKE(WindowMaker, 0.80.1) +AM_INIT_AUTOMAKE(WindowMaker, 0.80.2) AC_PROG_LIBTOOL @@ -100,7 +100,7 @@ dnl not used anywhere dnl AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_FUNC_ALLOCA -AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setpgid atexit mallinfo mkstemp snprintf vsnprintf asprintf vasprintf) +AC_CHECK_FUNCS(gethostname select poll strerror strcasecmp strncasecmp setsid atexit mallinfo mkstemp snprintf vsnprintf asprintf vasprintf) dnl ripped from samba diff --git a/src/dock.c b/src/dock.c index a893c4ef..8a61545e 100644 --- a/src/dock.c +++ b/src/dock.c @@ -2979,8 +2979,8 @@ execCommand(WAppIcon *btn, char *command, WSavedState *state) SetupEnvironment(scr); -#ifdef HAVE_SETPGID - setpgid(0, 0); +#ifdef HAVE_SETSID + setsid(); #endif args = malloc(sizeof(char*)*(argc+1)); diff --git a/src/main.c b/src/main.c index 8b408bac..ad576543 100644 --- a/src/main.c +++ b/src/main.c @@ -307,8 +307,8 @@ ExecuteShellCommand(WScreen *scr, char *command) SetupEnvironment(scr); -#ifdef HAVE_SETPGID - setpgid(0, 0); +#ifdef HAVE_SETSID + setsid(); #endif execl(shell, shell, "-c", command, NULL); wsyserror("could not execute %s -c %s", shell, command); -- 2.11.4.GIT