[Ur] redirect breaks channels

Sergey Mironov grrwlf at gmail.com
Tue Dec 24 19:24:21 EST 2013


OK, I've looked under the hood and now I see that my application is
invalid because we can't call recv() on channels obtained from
anywhere but the channel call. I agree, that otherwise we would
provoke a security weakness. But also it means that channel API
signatures (in basis.urs) do not describe the server-side
implementation correctly. I would suggest writing something like

con channel :: Type -> Type
con channelw :: Type -> Type (* the write end of a channel *)

val channel : t ::: Type -> transaction (channel t)
val channelw : t ::: Type -> channel t -> channelw t

val send : t ::: Type -> channelw t -> t -> transaction unit
val recv : t ::: Type -> channel t -> transaction t

and define sqlifiers for 'channelw' but not for 'channel' to forbid
calling recv on anything but the valid channel. Maybe it is possible
to do with minimal changes in C code.

Unfortunately, rewriting my program didn't help me to deal with errors
[1] . I see them in correctly written programs as well. Is it the
concurrency problem you mentioned in the manual? Could you please
explain in a bit more details why do we need to start a transaction
within a transaction here?

[1] Begin error: cannot start a transaction within a
transaction<br/>Expunge blocked by error: Error running SQL BEGIN

Regards,
Sergey


2013/12/25 Sergey Mironov <grrwlf at gmail.com>:
> Hi.
> I've faced a channel issue. Looks like I can't put a value into a
> channel from the transaction which didn't create that channel using
> `channel' function. Consider the following program:
>
> table t : { Id : int , Chan : channel int }
>
> fun put (i:int) =
>     r <- oneRow1(SELECT * FROM t WHERE t.Id = 0);
>     Basis.send r.Chan i
>
> fun monitor {} : transaction page =
>   r <- oneRow1(SELECT * FROM t WHERE t.Id = 0);
>   ch <- return r.Chan;
>   let
>       fun ping () =
>         i <- recv ch;
>         alert (show i);
>         ping ()
>   in
>       return
>        <xml>
>         <body onload={ping ()}>
>           <button value="Send a value" onclick={fn x => rpc (put 33)}/>
>         </body>
>        </xml>
>   end
>
> fun main () : transaction page =
>     ch <- channel;
>     dml(INSERT INTO t (Id,Chan) VALUES (0,{[ch]}));
>     redirect (url (monitor ()))
>
>
> The monitor here doesn't receive any messages from the channel,
> despite the fact that there is only one channel in the database. But
> if I move
>     ch <- channel; dml(INSERT INTO t (Id,Chan) VALUES (0,{[ch]}));
> lines from main to the monitor's body, everything works. Please
> suggest a fix/workaround!
>
> Merry christmas to all
>
> Sergey
>
> PS
>
> Application reports
> Begin error: cannot start a transaction within a transaction<br
> />Expunge blocked by error: Error running SQL BEGIN
> Note, I'm using sqlite engine. I've tried it using vanilla urweb too:)
> The source is in attach.



More information about the Ur mailing list