aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2010-09-10 15:15:04 +1000
committerSteve Bennett <steveb@workware.net.au>2010-10-15 11:02:51 +1000
commit38733caf6dc5e8556283c62468d0b3f20d5911dd (patch)
tree6b527d13a02bcfdfaf0c98daa321f6da0167d7f3
parentfe33a846cd13edf9440b81756896105ab4a86680 (diff)
downloadjimtcl-38733caf6dc5e8556283c62468d0b3f20d5911dd.zip
jimtcl-38733caf6dc5e8556283c62468d0b3f20d5911dd.tar.gz
jimtcl-38733caf6dc5e8556283c62468d0b3f20d5911dd.tar.bz2
Fix some eventloop problems
File handlers now pass through the error code and the handler is deleted on error. If there is nothing to do, vwait returns. If bgerror doesn't exist, print the original error to stderr. Also remove the 'eof' event handler since it isn't needed. Can just call [eof $f]. This also fixes source locations within 'readable' scripts. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim-aio.c66
-rw-r--r--jim-eventloop.c19
-rw-r--r--jim.c2
-rw-r--r--jim_tcl.txt11
4 files changed, 41 insertions, 57 deletions
diff --git a/jim-aio.c b/jim-aio.c
index d717911..a6412ef 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -642,62 +642,42 @@ static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask)
{
Jim_Obj *objPtr = clientData;
- Jim_Obj *scrPtr = NULL;
- if (mask == (JIM_EVENT_READABLE | JIM_EVENT_FEOF)) {
- Jim_ListIndex(interp, objPtr, 1, &scrPtr, 0);
- }
- else {
- Jim_ListIndex(interp, objPtr, 0, &scrPtr, 0);
- }
- Jim_EvalObjBackground(interp, scrPtr);
- return 0;
+ return Jim_EvalObjBackground(interp, objPtr);
}
-static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptListObj,
- Jim_Obj *script1, Jim_Obj *script2)
+static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj,
+ int argc, Jim_Obj * const *argv)
{
int scriptlen = 0;
- if (script1 == NULL) {
+ if (argc == 0) {
/* Return current script */
- if (*scriptListObj) {
- Jim_SetResult(interp, *scriptListObj);
+ if (*scriptHandlerObj) {
+ Jim_SetResult(interp, *scriptHandlerObj);
}
return JIM_OK;
}
- if (*scriptListObj) {
+ if (*scriptHandlerObj) {
/* Delete old handler */
Jim_DeleteFileHandler(interp, af->fp);
- *scriptListObj = NULL;
+ *scriptHandlerObj = NULL;
}
/* Now possibly add the new script(s) */
- Jim_GetString(script1, &scriptlen);
+ Jim_GetString(argv[0], &scriptlen);
if (scriptlen == 0) {
/* Empty script, so done */
return JIM_OK;
}
/* A new script to add */
- *scriptListObj = Jim_NewListObj(interp, NULL, 0);
- Jim_IncrRefCount(*scriptListObj);
-
- if (Jim_IsShared(script1)) {
- script1 = Jim_DuplicateObj(interp, script1);
- }
- Jim_ListAppendElement(interp, *scriptListObj, script1);
-
- if (script2) {
- if (Jim_IsShared(script2)) {
- script2 = Jim_DuplicateObj(interp, script2);
- }
- Jim_ListAppendElement(interp, *scriptListObj, script2);
- }
+ Jim_IncrRefCount(argv[0]);
+ *scriptHandlerObj = argv[0];
Jim_CreateFileHandler(interp, af->fp, mask,
- JimAioFileEventHandler, *scriptListObj, JimAioFileEventFinalizer);
+ JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer);
return JIM_OK;
}
@@ -705,32 +685,22 @@ static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Ob
static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- Jim_Obj *eofScript = NULL;
- int mask = JIM_EVENT_READABLE;
-
- if (argc == 2) {
- mask |= JIM_EVENT_FEOF;
- eofScript = argv[1];
- }
-
- return aio_eventinfo(interp, af, mask, &af->rEvent, argc ? argv[0] : NULL, eofScript);
+ return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv);
}
static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- int mask = JIM_EVENT_WRITABLE;
- return aio_eventinfo(interp, af, mask, &af->wEvent, argc ? argv[0] : NULL, NULL);
+ return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv);
}
static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- int mask = JIM_EVENT_EXCEPTION;
- return aio_eventinfo(interp, af, mask, &af->eEvent, argc ? argv[0] : NULL, NULL);
+ return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv);
}
#endif
@@ -811,11 +781,11 @@ static const jim_subcmd_type aio_command_table[] = {
#endif
#ifdef jim_ext_eventloop
{ .cmd = "readable",
- .args = "?readable-script ?eof-script??",
+ .args = "?readable-script?",
.minargs = 0,
- .maxargs = 2,
+ .maxargs = 1,
.function = aio_cmd_readable,
- .description = "Returns script, or invoke readable-script when readable, eof-script on eof, {} to remove",
+ .description = "Returns script, or invoke readable-script when readable, {} to remove",
},
{ .cmd = "writable",
.args = "?writable-script?",
diff --git a/jim-eventloop.c b/jim-eventloop.c
index 7c17ec8..ec8bfd1 100644
--- a/jim-eventloop.c
+++ b/jim-eventloop.c
@@ -236,7 +236,9 @@ static Jim_TimeEvent *JimSearchNearestTimer(Jim_EventLoop * eventLoop)
* if flags has JIM_DONT_WAIT set the function returns ASAP until all
* the events that's possible to process without to wait are processed.
*
- * The function returns the number of events processed. */
+ * The function returns the number of events processed or -1 if
+ * there are no matching handlers
+ */
int Jim_ProcessEvents(Jim_Interp *interp, int flags)
{
int maxfd = 0, numfd = 0, processed = 0;
@@ -246,7 +248,13 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
Jim_TimeEvent *te;
jim_wide maxId;
- JIM_NOTUSED(flags);
+ if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) {
+ /* No file events */
+ if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) {
+ /* No time events */
+ return -1;
+ }
+ }
FD_ZERO(&rfds);
FD_ZERO(&wfds);
@@ -321,7 +329,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
mask |= JIM_EVENT_WRITABLE;
if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds))
mask |= JIM_EVENT_EXCEPTION;
- if (fe->fileProc(interp, fe->clientData, mask) == JIM_ERR) {
+ if (fe->fileProc(interp, fe->clientData, mask) != JIM_OK) {
/* Remove the element on handler error */
Jim_DeleteFileHandler(interp, fe->handle);
}
@@ -417,7 +425,10 @@ static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
while (1) {
Jim_Obj *currValue;
- Jim_ProcessEvents(interp, JIM_ALL_EVENTS);
+ if (Jim_ProcessEvents(interp, JIM_ALL_EVENTS) < 0) {
+ /* Nothing level to process */
+ break;
+ }
currValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE);
/* Stop the loop if the vwait-ed variable changed value,
* or if was unset and now is set (or the contrary). */
diff --git a/jim.c b/jim.c
index 6d9d8bc..5b7b5d7 100644
--- a/jim.c
+++ b/jim.c
@@ -9900,7 +9900,7 @@ int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
objv[1] = Jim_GetResult(interp);
Jim_IncrRefCount(objv[0]);
Jim_IncrRefCount(objv[1]);
- if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) {
+ if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || Jim_EvalObjVector(interp, 2, objv) != JIM_OK) {
/* Report the error to stderr. */
fprintf(stderr, "Background error:" JIM_NL);
Jim_PrintErrorMessage(interp);
diff --git a/jim_tcl.txt b/jim_tcl.txt
index 4299d37..62e8990 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -76,6 +76,7 @@ Since v0.62:
13. It is now possible to 'return' from within 'try'
14. IPv6 support is now included
15. Add 'string is'
+16. Event handlers works better if an error occurs. eof handler has been removed.
Since v0.61:
@@ -3989,15 +3990,17 @@ eventloop: after, vwait
~~~~~~~~~~~~~~~~~~~~~~~
The following commands allow a script to be invoked when the given condition occurs.
+If no script is given, returns the current script. If the given script is the empty, the
+handler is removed.
-+$handle *readable* '?readable-script ?eof-script??'+::
- Returns script, or invoke readable-script when readable, eof-script on eof, {} to remove
++$handle *readable* '?readable-script?'+::
+ Sets or returns the script for when the socket is readable.
+$handle *writable* '?writable-script?'+::
- Returns script, or invoke writable-script when writable, {} to remove
+ Sets or returns the script for when the socket is writable.
+$handle *onexception* '?exception-script?'+::
- Returns script, or invoke exception-script when oob data, {} to remove
+ Sets or returns the script for when when oob data received.
Time-based execution is also available via the eventloop API.