aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/js/urweb.js24
-rw-r--r--src/c/urweb.c27
-rw-r--r--src/cjr_print.sig2
-rw-r--r--src/cjr_print.sml6
-rw-r--r--src/compiler.sig3
-rw-r--r--src/compiler.sml42
-rw-r--r--src/demo.sml1
-rw-r--r--tests/channel.urp1
8 files changed, 76 insertions, 30 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index be1aea08..6d405347 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -141,6 +141,7 @@ function cr(n) {
var client_id = 0;
var client_pass = 0;
var url_prefix = "/";
+var timeout = 60;
function getXHR(uri)
{
@@ -234,8 +235,18 @@ function newChannel() {
function listener() {
var uri = path_join(url_prefix, ".msgs");
var xhr = getXHR();
- var orsc = function() {
+ var tid, orsc, onTimeout;
+
+ var connect = function () {
+ xhr.onreadystatechange = orsc;
+ tid = window.setTimeout(onTimeout, timeout * 500);
+ requestUri(xhr, uri);
+ }
+
+ orsc = function() {
if (xhr.readyState == 4) {
+ window.clearTimeout(tid);
+
var isok = false;
try {
@@ -271,8 +282,7 @@ function listener() {
}
}
- xhr.onreadystatechange = orsc;
- requestUri(xhr, uri);
+ connect();
}
else {
try {
@@ -282,8 +292,12 @@ function listener() {
}
};
- xhr.onreadystatechange = orsc;
- requestUri(xhr, uri);
+ onTimeout = function() {
+ xhr.abort();
+ connect();
+ };
+
+ connect();
}
function rv(chn, parse, k) {
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 6cc786ef..5fa2af42 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -220,10 +220,8 @@ void uw_client_connect(size_t id, int pass, int sock) {
}
if (c->data.used.sock != -1) {
- pthread_mutex_unlock(&c->data.used.lock);
- close(sock);
- fprintf(stderr, "Duplicate client connection (%d)\n", (int)id);
- return;
+ close(c->data.used.sock);
+ c->data.used.sock = -1;
}
c->data.used.last_contact = time(NULL);
@@ -288,11 +286,13 @@ static void uw_free_client(client *c) {
}
}
-void uw_prune_clients(time_t timeout) {
+extern int uw_timeout;
+
+void uw_prune_clients() {
size_t i;
time_t cutoff;
- cutoff = time(NULL) - timeout;
+ cutoff = time(NULL) - uw_timeout;
pthread_mutex_lock(&clients_mutex);
@@ -507,6 +507,8 @@ struct uw_context {
size_t n_deltas;
channel_delta *deltas;
+ int timeout;
+
char error_message[ERROR_BUF_LEN];
};
@@ -541,6 +543,8 @@ uw_context uw_init(size_t outHeaders_len, size_t script_len, size_t page_len, si
ctx->n_deltas = 0;
ctx->deltas = malloc(0);
+ ctx->timeout = uw_timeout;
+
return ctx;
}
@@ -834,10 +838,15 @@ const char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
int pass;
client *c = uw_new_client(&pass);
- char *r = uw_malloc(ctx, strlen(ctx->script_header) + 56 + 2 * INTS_MAX + buf_used(&ctx->script)
+ char *r = uw_malloc(ctx, strlen(ctx->script_header) + 65 + 3 * INTS_MAX + buf_used(&ctx->script)
+ strlen(ctx->url_prefix));
- sprintf(r, "%s<script>client_id=%d;client_pass=%d;url_prefix=\"%s\";%s</script>",
- ctx->script_header, (int)c->id, c->data.used.pass, ctx->url_prefix, ctx->script.start);
+ sprintf(r, "%s<script>client_id=%d;client_pass=%d;url_prefix=\"%s\";timeout=%d;%s</script>",
+ ctx->script_header,
+ (int)c->id,
+ c->data.used.pass,
+ ctx->url_prefix,
+ ctx->timeout,
+ ctx->script.start);
return r;
}
}
diff --git a/src/cjr_print.sig b/src/cjr_print.sig
index baef005e..d7fb21a0 100644
--- a/src/cjr_print.sig
+++ b/src/cjr_print.sig
@@ -36,4 +36,6 @@ signature CJR_PRINT = sig
val p_sql : CjrEnv.env -> Cjr.file Print.printer
val debug : bool ref
+
+ val timeout : int ref
end
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index c5931616..79a43d19 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -1124,6 +1124,8 @@ fun urlify env t =
urlify' IS.empty 0 t
end
+val timeout = ref 0
+
fun p_exp' par env (e, loc) =
case e of
EPrim p => Prim.p_t_GCC p
@@ -2688,6 +2690,10 @@ fun p_file env (ds, ps) =
string (Int.toString (SM.foldl Int.max 0 fnums + 1)),
string ";",
newline,
+ string "int uw_timeout = ",
+ string (Int.toString (!timeout)),
+ string ";",
+ newline,
newline,
string "int uw_input_num(char *name) {",
newline,
diff --git a/src/compiler.sig b/src/compiler.sig
index 8ef41a58..025a6bcd 100644
--- a/src/compiler.sig
+++ b/src/compiler.sig
@@ -36,7 +36,8 @@ signature COMPILER = sig
exe : string,
sql : string option,
debug : bool,
- profile : bool
+ profile : bool,
+ timeout : int
}
val compile : string -> unit
val compileC : {cname : string, oname : string, ename : string, libs : string, profile : bool} -> unit
diff --git a/src/compiler.sml b/src/compiler.sml
index b433a7b6..f9200731 100644
--- a/src/compiler.sml
+++ b/src/compiler.sml
@@ -42,7 +42,8 @@ type job = {
exe : string,
sql : string option,
debug : bool,
- profile : bool
+ profile : bool,
+ timeout : int
}
type ('src, 'dst) phase = {
@@ -200,7 +201,7 @@ val parseUr = {
handle LrParser.ParseError => [],
print = SourcePrint.p_file}
-fun p_job {prefix, database, exe, sql, sources, debug, profile} =
+fun p_job {prefix, database, exe, sql, sources, debug, profile, timeout} =
let
open Print.PD
open Print
@@ -223,6 +224,10 @@ fun p_job {prefix, database, exe, sql, sources, debug, profile} =
case sql of
NONE => string "No SQL file."
| SOME sql => string ("SQL fle: " ^ sql),
+ newline,
+ string "Timeout: ",
+ string (Int.toString timeout),
+ newline,
string "Sources:",
p_list string sources,
newline]
@@ -265,7 +270,7 @@ val parseUrp = {
readSources acc
end
- fun finish (prefix, database, exe, sql, debug, profile, sources) =
+ fun finish (prefix, database, exe, sql, debug, profile, timeout, sources) =
{prefix = Option.getOpt (prefix, "/"),
database = database,
exe = Option.getOpt (exe, OS.Path.joinBaseExt {base = OS.Path.base filename,
@@ -273,12 +278,13 @@ val parseUrp = {
sql = sql,
debug = debug,
profile = profile,
+ timeout = Option.getOpt (timeout, 60),
sources = sources}
- fun read (prefix, database, exe, sql, debug, profile) =
+ fun read (prefix, database, exe, sql, debug, profile, timeout) =
case TextIO.inputLine inf of
- NONE => finish (prefix, database, exe, sql, debug, profile, [])
- | SOME "\n" => finish (prefix, database, exe, sql, debug, profile, readSources [])
+ NONE => finish (prefix, database, exe, sql, debug, profile, timeout, [])
+ | SOME "\n" => finish (prefix, database, exe, sql, debug, profile, timeout, readSources [])
| SOME line =>
let
val (cmd, arg) = Substring.splitl (fn x => not (Char.isSpace x)) (Substring.full line)
@@ -290,32 +296,38 @@ val parseUrp = {
(case prefix of
NONE => ()
| SOME _ => ErrorMsg.error "Duplicate 'prefix' directive";
- read (SOME arg, database, exe, sql, debug, profile))
+ read (SOME arg, database, exe, sql, debug, profile, timeout))
| "database" =>
(case database of
NONE => ()
| SOME _ => ErrorMsg.error "Duplicate 'database' directive";
- read (prefix, SOME arg, exe, sql, debug, profile))
+ read (prefix, SOME arg, exe, sql, debug, profile, timeout))
| "exe" =>
(case exe of
NONE => ()
| SOME _ => ErrorMsg.error "Duplicate 'exe' directive";
- read (prefix, database, SOME (relify arg), sql, debug, profile))
+ read (prefix, database, SOME (relify arg), sql, debug, profile, timeout))
| "sql" =>
(case sql of
NONE => ()
| SOME _ => ErrorMsg.error "Duplicate 'sql' directive";
- read (prefix, database, exe, SOME (relify arg), debug, profile))
- | "debug" => read (prefix, database, exe, sql, true, profile)
- | "profile" => read (prefix, database, exe, sql, debug, true)
+ read (prefix, database, exe, SOME (relify arg), debug, profile, timeout))
+ | "debug" => read (prefix, database, exe, sql, true, profile, timeout)
+ | "profile" => read (prefix, database, exe, sql, debug, true, timeout)
+ | "timeout" =>
+ (case timeout of
+ NONE => ()
+ | SOME _ => ErrorMsg.error "Duplicate 'timeout' directive";
+ read (prefix, database, exe, sql, debug, profile, SOME (valOf (Int.fromString arg))))
| _ => (ErrorMsg.error ("Unrecognized command '" ^ cmd ^ "'");
- read (prefix, database, exe, sql, debug, profile))
+ read (prefix, database, exe, sql, debug, profile, timeout))
end
- val job = read (NONE, NONE, NONE, NONE, false, false)
+ val job = read (NONE, NONE, NONE, NONE, false, false, NONE)
in
TextIO.closeIn inf;
Monoize.urlPrefix := #prefix job;
+ CjrPrint.timeout := #timeout job;
job
end,
print = p_job
@@ -598,7 +610,7 @@ fun compileC {cname, oname, ename, libs, profile} =
else if not (OS.Process.isSuccess (OS.Process.system link)) then
print "C linking failed\n"
else
- print "Success\n"
+ ()
end
fun compile job =
diff --git a/src/demo.sml b/src/demo.sml
index 4f0cb52e..43fa5ef0 100644
--- a/src/demo.sml
+++ b/src/demo.sml
@@ -93,6 +93,7 @@ fun make {prefix, dirname, guided} =
sql = SOME (OS.Path.joinDirFile {dir = dirname,
file = "demo.sql"}),
debug = false,
+ timeout = Int.max (#timeout combined, #timeout urp),
profile = false
}
diff --git a/tests/channel.urp b/tests/channel.urp
index d49aa728..167899c4 100644
--- a/tests/channel.urp
+++ b/tests/channel.urp
@@ -1,3 +1,4 @@
debug
+timeout 10
channel