From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id A74CB7EE9C for ; Sun, 27 Nov 2016 22:05:11 +0100 (CET) Authentication-Results: mail3-smtp-sop.national.inria.fr; spf=None smtp.pra=antronbachin@gmail.com; spf=Pass smtp.mailfrom=antronbachin@gmail.com; spf=None smtp.helo=postmaster@mail-io0-f195.google.com Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of antronbachin@gmail.com) identity=pra; client-ip=209.85.223.195; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="antronbachin@gmail.com"; x-sender="antronbachin@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of antronbachin@gmail.com designates 209.85.223.195 as permitted sender) identity=mailfrom; client-ip=209.85.223.195; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="antronbachin@gmail.com"; x-sender="antronbachin@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-io0-f195.google.com) identity=helo; client-ip=209.85.223.195; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="antronbachin@gmail.com"; x-sender="postmaster@mail-io0-f195.google.com"; x-conformance=sidf_compatible IronPort-PHdr: =?us-ascii?q?9a23=3ALY26pBKV4WROA/LbXNmcpTZWNBhigK39O0sv0rFi?= =?us-ascii?q?tYgfLvjxwZ3uMQTl6Ol3ixeRBMOAuqkC0Lad6vywEUU7or+5+EgYd5JNUxJXwe?= =?us-ascii?q?43pCcHRPC/NEvgMfTxZDY7FskRHHVs/nW8LFQHUJ2mPw6arXK99yMdFQviPgRp?= =?us-ascii?q?OOv1BpTSj8Oq3Oyu5pHfeQtFiT6zbL9oIhi7ogrdutQZjIZhN6081gbHrnxUdu?= =?us-ascii?q?pM2GhmP0iTnxHy5sex+J5s7SFdsO8/+sBDTKv3Yb02QaRXAzo6PW814tbrtQTY?= =?us-ascii?q?QguU+nQcSGQWnQFWDAXD8Rr3Q43+sir+tup6xSmaIcj7Rq06VDi+86tmTgLjhT?= =?us-ascii?q?wZPDAl7m7Yls1wjLpaoB2/oRx/35XUa5yROPZnY6/RYc8WSW9HU81MVSJOH5m8?= =?us-ascii?q?YpMTAOUOIOhWr4vyqVUNoxuwGweiA/jixSVUin/zx6A60/gtHAPA0Qc9H9wOqn?= =?us-ascii?q?PUrNDtOaoOV+C10K7IzTPeZP5Lwzjy9IjIchEnofqRWr9/a8zRyVU1FwPCiFWf?= =?us-ascii?q?spbqMC+V1uQMtWiW9OVgVee1hG4mrwF9uCSgxsApioTQgI8e117K9SJ8wIkvJN?= =?us-ascii?q?24TlZ2Yca+H5tLqyGaNpV5TtklQ2FytyY20rgGuJ68fCkEzpQo2gXQZ+abfIiP?= =?us-ascii?q?5xLvTOiRITBjhH14Zr2/ggy+8U+6yu3zUMS/zVVErjJdn9XSqnwA0wbf58uHR/?= =?us-ascii?q?dn4EutxziC2xrO5uxAIU04jbTXJp89zrItk5cfr0vOEjPzlUrqjaKaalko9+2r?= =?us-ascii?q?5uv8f7rqupqROoBohg7iL6sjn8KyDOA8PwQTWmWW+P+z26Dm8ED5XbpHjuE5n6?= =?us-ascii?q?/Eu57AP8sbvLS2AwpN34Yj9Rm/CzCm3cwdnXYdLVJFfAuLj4nuO13SOfz4A+qz?= =?us-ascii?q?jlCsnTtxyPDGObrhAprJLnfdirvuYbF960tExAoyy9BQ+Y5UB6kfLP7vXkL9rt?= =?us-ascii?q?/VAx8jPwCq3erqBs9x2p4aVG+PGqOZNbndsV6M5uIhOemMY4oVtS7nJPgj+/7u?= =?us-ascii?q?l3g5mVkGcqazwZQXaHG4HvJ9LkWWZHrjmNYBEWMQsgUiS+zqjUWOUSRPaHaqQ6?= =?us-ascii?q?I8+jY7BZq6AojZQ4CthKWN3CO6Hp1NemBLEUuMEHftd4WcQfgAciOSIsl7kjwF?= =?us-ascii?q?T7etUYEh1Qv9/DP9noBuNurd9ylQn5v+2MV04aWHjxs29CdoFOyS1miMSyd/mW?= =?us-ascii?q?ZeFBEs26UqiEphzVHL+6Fzg/1eXYha4e9TVQEwPJXczupSBNX7WwaHddCMHgX1?= =?us-ascii?q?Cu66CC08G4pii+QFZFxwTpD71kjO?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A0CBAAC9STtYZ8PfVdFeHQEFAQsBFwEBB?= =?us-ascii?q?AEBCgEBgmkkAQEBAQEfWH0GpGGPVYcmJIJHgzYCgWZCEQEBAQEBAQEBAQEBEgs?= =?us-ascii?q?LCwcdMoIzGgGCGgEBAQMBEhEEGQEUBx0BAwELBgUHBAMKJwMCAiECEQEFAQsRB?= =?us-ascii?q?hMJGYgwAQMPCAEInnuBMj8yi1CBbBgFAR+DDQWDTQoZJw1UgzYBAQEBAQEBAQE?= =?us-ascii?q?BAQEBAQEBAQEBAQEUAgYJAQiIKQiBToEIgkiBa4MaLYIwBY9thH6FNDWGSIZog?= =?us-ascii?q?1YKgjeHOIY5iUACHYN/E4JIMYETNE8ZLkAOAQEBgRcBgX+CJ1OIdQEBAQ?= X-IPAS-Result: =?us-ascii?q?A0CBAAC9STtYZ8PfVdFeHQEFAQsBFwEBBAEBCgEBgmkkAQE?= =?us-ascii?q?BAQEfWH0GpGGPVYcmJIJHgzYCgWZCEQEBAQEBAQEBAQEBEgsLCwcdMoIzGgGCG?= =?us-ascii?q?gEBAQMBEhEEGQEUBx0BAwELBgUHBAMKJwMCAiECEQEFAQsRBhMJGYgwAQMPCAE?= =?us-ascii?q?InnuBMj8yi1CBbBgFAR+DDQWDTQoZJw1UgzYBAQEBAQEBAQEBAQEBAQEBAQEBA?= =?us-ascii?q?QEUAgYJAQiIKQiBToEIgkiBa4MaLYIwBY9thH6FNDWGSIZog1YKgjeHOIY5iUA?= =?us-ascii?q?CHYN/E4JIMYETNE8ZLkAOAQEBgRcBgX+CJ1OIdQEBAQ?= X-IronPort-AV: E=Sophos;i="5.31,560,1473112800"; d="scan'208,217";a="201900359" Received: from mail-io0-f195.google.com ([209.85.223.195]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/AES128-GCM-SHA256; 27 Nov 2016 22:05:09 +0100 Received: by mail-io0-f195.google.com with SMTP id j92so19080953ioi.0 for ; Sun, 27 Nov 2016 13:05:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:subject:from:in-reply-to:date:cc:message-id:references :to; bh=VbkKBgYdM/G+mEVdj+J7xlexd0J8LhZbjwNxxY47VS0=; b=D/RN/ITlfCwDqwOYETig968mWQ7R/npPa1dUEaFF97TXSAx+jcr1V9tnB1ut67ylfM jwfS0LHAyOEjgoV0binNwplgWCnCJSm7Mffb5gxTtl5OqjXnIAIhKka4lExQHgTRMati +BHZ4ewn2HAogMnjo3vjO2c6T4PzaxSzUTpJ375n4km98UPYCPoYpZDFE0Lf7rIp5fOr V6sLaBQdhZaoFRc4gop7nJcCx7jKbDfOxqV+XEnsjQzR6TgLPx6IQqieLXT/0P2Igwsp NtoMB9H/LdH5fDsRcxT9GIO45URT+YZrWbFiIPx5pooRbT2aoD/YgEayZXfDvIbPrzTS 7QHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:subject:from:in-reply-to:date:cc :message-id:references:to; bh=VbkKBgYdM/G+mEVdj+J7xlexd0J8LhZbjwNxxY47VS0=; b=hM42p45mN2SCdge3a/UGjvEPsYTwnz/AWQ2kYMwaoM/itnOFRoHmk4GHXzh454U2KN xBssL3igSLsMaPGMPrpXcBK08QsXH72WwHWEmaMHv63K3nMo/uO2ZD5rV+ckUuFpQ3mB ubEUX4lpsKZuQOrU0mVP+lVigE6TiHbYKZDcaxr3USJtMO0wmA//odFw1YCzbvgmDgQE tqQpvSBWhZtk/acqnNNN08z7S58gouG6EuDlVetnG1knFBZRryafCdTSly/clSBaliOA trvFISleQtB99vdXAqSBYIRGmLmrY4AV9Gtc7m5Zs0B5ZDFS5zSte0kxFjVKhWTGsITs C99Q== X-Gm-Message-State: AKaTC02q/u8WP4T4cymQ4C63YQ4ZOaGNHSBrRyL0IRHpEo7mlvUrrqEuQ2j7U8MMyo7wkw== X-Received: by 10.107.6.223 with SMTP id f92mr14725098ioi.2.1480280708273; Sun, 27 Nov 2016 13:05:08 -0800 (PST) Received: from ?IPv6:2601:240:c600:8bd0:40cd:3991:6bd:5d5c? ([2601:240:c600:8bd0:40cd:3991:6bd:5d5c]) by smtp.gmail.com with ESMTPSA id s188sm7451661itb.13.2016.11.27.13.05.07 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 27 Nov 2016 13:05:07 -0800 (PST) Content-Type: multipart/alternative; boundary="Apple-Mail=_C8ED71A8-3690-4149-BDA7-54ACF0044951" Mime-Version: 1.0 (Mac OS X Mail 8.2 \(2070.6\)) From: Anton Bachin In-Reply-To: Date: Sun, 27 Nov 2016 15:05:06 -0600 Cc: Koen De Keyser , caml-list@inria.fr X-Mao-Original-Outgoing-Id: 501973506.57243-458c63d7d2c1fdf255b12abf8a049f96 Message-Id: References: To: Raphael Bauduin X-Mailer: Apple Mail (2.2070.6) Subject: Re: [Caml-list] Beginner's question on Lwt usage --Apple-Mail=_C8ED71A8-3690-4149-BDA7-54ACF0044951 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi Raphael, The problem with not being able to close connection 2 while connection 1 is= still being serviced is likely due to this code using system call function= s from module Unix, rather than Lwt_unix (or other Lwt modules). Lwt doesn= =E2=80=99t turn Unix module system calls, such as Unix.recv, into non-block= ing ones =E2=80=93 they can still block your whole program, even if you use= Lwt elsewhere in it. Only the Lwt_unix system call functions are non-block= ing. To get good results, you have to switch to using those when you switch= to Lwt. There are several other problems of a similar flavor. For example, Lwt.retu= rn (Unix.accept sock) doesn=E2=80=99t create a thread that runs Unix.accept= in the background. What that actually does is: it blocks the whole process= until Unix.accept completes. Then, it wraps the result of Unix.accept in a= =E2=80=9Calready-finished=E2=80=9D Lwt thread (admittedly, the existing Lw= t docs are a bit vague on this). There is then no use in =E2=80=9Cbinding= =E2=80=9D on that thread: it just takes out that result, and is equivalent = to simply doing "let fd, caller =3D Unix.accept sock in=E2=80=9D. The Lwt w= ay would be open Lwt.Infix Lwt_unix.accept sock' >>=3D fun (fd, caller) -> =E2=80=A6 or let%lwt fd, caller =3D Lwt_unix.accept sock=E2=80=99 in (* if building= with lwt.ppx *) ... where sock=E2=80=99 is created by =E2=80=9CLwt_unix.of_unix_file_descr sock= =E2=80=9D, or better, directly by calling Lwt_unix.socket in the first plac= e. In general, Lwt threads don=E2=80=99t correspond to system threads, so you = can=E2=80=99t just wrap existing code in Lwt.return and Lwt.bind, and expec= t it to become concurrent. Lwt threads correspond to promises (a.k.a. green= threads, pick your term), so you have to use "promise-friendly" versions o= f everything. If you=E2=80=99d like to discuss this, or your code, in some detail, I reco= mmend #ocaml on freenode. I lurk there, as do many other Lwt users, and we = can quickly go back and forth :) Best, Anton > El nov 27, 2016, a las 12:59, Raphael Bauduin > escribi=C3=B3: >=20 > Thanks for your answer! >=20 > I get the same result with the following code. Note that I can open 2 con= nections and that the closing of the connection works as expected with a 'c= lose connection' pattern (with one line only with a dot followed by an empt= y line). It is just that I cannot close the second connection while the fir= st stays open, the 'close connection' pattern is not triggering the close. >=20 > let rec accept_connection sock:Unix.file_descr =3D > let socket_thread =3D Lwt.return ( Unix.accept sock ) in > let _ =3D Lwt.bind socket_thread > ( fun (fd, caller) -> > ignore(Lwt_io.printf "accepted\n%!"); > (*let _ =3D set_nonblock fd in*) > Lwt.return (readall fd) >>=3D fun a -> > ignore(Lwt_io.printf "%s\n%!" a); > ignore(Lwt.async (fun () -> Lwt.return (close fd) ) ); > Lwt.return 0; > ); in > accept_connection sock > let server port =3D > let inet_addr =3D inet_addr_any in > let sockaddr =3D ADDR_INET (inet_addr, port) in > let domain =3D domain_of_sockaddr sockaddr in > let sock:Unix.file_descr =3D socket domain SOCK_STREAM 0 in > Unix.bind sock sockaddr; > listen sock 10; > Lwt_main.run ( Lwt.return (accept_connection sock) ) >=20 >=20 > On Sun, Nov 27, 2016 at 6:41 PM, Koen De Keyser > wrote: > You need to run your lwt code within Lwt_main.run=20 >=20 > This starts the lwt scheduler. Otherwise your application just terminates= once it has created the lwt thread (which is a simple Ocaml value).=20 >=20 > Koen >=20 > On Nov 27, 2016 18:30, "Raphael Bauduin" > wrote: > Hi, >=20 > After writing a small tcp server in ocaml, I wanted to make it work async= hronously with Lwt. > I changed the function handling the accept on the socket to look like thi= s: >=20 > let rec accept_connection sock:Unix.file_descr =3D > let socket_thread =3D Lwt.return ( Unix.accept sock ) in > let _ =3D Lwt.bind socket_thread > ( fun (fd, caller) -> > ignore(Lwt_io.printf "accepted\n%!"); > (*let _ =3D set_nonblock fd in*) > Lwt.return (readall fd) >>=3D fun a -> > ignore(Lwt_io.printf "%s\n%!" a); > ignore(Lwt.async (fun () -> Lwt.return (close fd) ) ); > Lwt.return 0; > ); in > accept_connection sock >=20 > The complete code is at http://pastie.org/10971189 . >=20 > But it doesn't seem to work. The problems are: > - nothing is printed on stdout > - when I open 2 connections, the second can only be closed after the firs= t has been closed. >=20 > In the mean time I've discovered Lwt_unix, but before looking at it, I'd = like to understand what's wrong in my current code. Can you spot errors in = the code? General advice is also welcome! >=20 > Thanks >=20 > Raphael >=20 >=20 >=20 >=20 >=20 > --=20 > Web database: http://www.myowndb.com > Free Software Developers Meeting: http://www.fosdem.org --Apple-Mail=_C8ED71A8-3690-4149-BDA7-54ACF0044951 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
Hi Ra= phael,

The proble= m with not being able to close connection 2 while connection 1 is still bei= ng serviced is likely due to this code using system call functions from mod= ule Unix, rather than Lwt_unix (or other Lwt modules). Lwt doesn=E2=80=99t = turn Unix module system calls, such as Unix.recv, into non-blocking ones = =E2=80=93 they can still block your whole program, even if you use Lwt else= where in it. Only the Lwt_unix system call functions are non-blocking. To g= et good results, you have to switch to using those when you switch to Lwt.<= /div>

There are several= other problems of a similar flavor. For example, Lwt.return (Unix.accept s= ock) doesn=E2=80=99t create a thread that runs Unix.accept in the backgroun= d. What that actually does is: it blocks the whole process until Unix.accep= t completes. Then, it wraps the result of Unix.accept in a =E2=80=9Calready= -finished=E2=80=9D Lwt thread (admittedly, the existing Lwt docs are a bit = vague on this). There is then no use in =E2=80=9Cbinding=E2=80=9D on that t= hread: it just takes out that result, and is equivalent to simply doing "le= t fd, caller =3D Unix.accept sock in=E2=80=9D. The Lwt way would be

  open Lwt.Infix

  Lwt_unix.acc= ept sock' >>=3D fun (fd, caller) ->
  = =E2=80=A6

or

  let%lwt fd, ca= ller =3D Lwt_unix.accept sock=E2=80=99 in    (* if building with = lwt.ppx *)
  ...

where sock=E2=80=99 is created by =E2=80=9CLwt_= unix.of_unix_file_descr sock=E2=80=9D, or better, directly by calling Lwt_u= nix.socket in the first place.

In general, Lwt threads don=E2=80=99t correspond to system th= reads, so you can=E2=80=99t just wrap existing code in Lwt.return and Lwt.b= ind, and expect it to become concurrent. Lwt threads correspond to promises= (a.k.a. green threads, pick your term), so you have to use "promise-friend= ly" versions of everything.

If you=E2=80=99d like to discuss this, or your code, in some det= ail, I recommend #ocaml on freenode. I lurk there, as do many other Lwt use= rs, and we can quickly go back and forth :)

Best,
Anton

= El nov 27, 2016, a las 12:59, Raphael Bauduin <rblists@gmail.com> escribi=C3=B3:

Thanks for your answer!

I get the same result with the following code. Note that I can open 2= connections and that the closing of the connection works as expected with = a 'close connection' pattern (with one line only with a dot followed by an = empty line). It is just that I cannot close the second connection while the= first stays open, the 'close connection' pattern is not triggering the clo= se.

let rec accept_connection sock:Unix.file_descr =3D
=   let socket_thread =3D Lwt.return ( Unix.accept sock ) in
    let _ =3D Lwt.bind socket_thread
           ( fun (fd, caller) ->
<= div class=3D"">               ignor= e(Lwt_io.printf "accepted\n%!");
      =          (*let _ =3D set_nonblock fd in*)
               Lwt.ret= urn (readall fd) >>=3D fun a ->
   =                ignore(Lwt_io.print= f "%s\n%!" a);
          &nbs= p;        ignore(Lwt.async (fun () -> Lwt.return (cl= ose fd) ) );
           =        Lwt.return 0;
   = ;        ); in
     = ;accept_connection sock
let server port =3D
  let inet_addr =3D inet_addr_any in
&= nbsp; let sockaddr =3D ADDR_INET (inet_addr, port) in
=   let domain =3D domain_of_sockaddr sockaddr in
&= nbsp; let sock:Unix.file_descr =3D socket domain SOCK_STREAM 0 in
  Unix.bind sock sockaddr;
  lis= ten sock 10;
  Lwt_main.run ( Lwt.return (accept_= connection sock) )


On Sun, = Nov 27, 2016 at 6:41 PM, Koen De Keyser <koen.= dekeyser@gmail.com> wrote:
You need to run your lwt code withi= n Lwt_main.run 

This starts the lwt scheduler. Otherwise your appli= cation just terminates once it has created the lwt thread (which is a simpl= e Ocaml value). 

Koen

On Nov 27, 2016 18:30, "Raphael Bauduin" <rblists@gmail.com> wrote:
Hi,

After writing a small = tcp server in ocaml, I wanted to make it work asynchronously with Lwt.
I changed the function handling the accept on the socket t= o look like this:

let rec accept_connection sock:Unix.file_descr =3D
  let socket_thread =3D Lwt.return ( Unix.accept sock ) = in
  let _ =3D Lwt.bind socket_thread
         ( fun (fd, caller) ->
<= div class=3D"">             ignore(Lwt_i= o.printf "accepted\n%!");
        =      (*let _ =3D set_nonblock fd in*)
&= nbsp;            Lwt.return (readall fd) >= >=3D fun a ->
         =        ignore(Lwt_io.printf "%s\n%!" a);
                 ignor= e(Lwt.async (fun () -> Lwt.return (close fd) ) );
&= nbsp;                Lwt.return 0;<= /div>
         ); in
   accept_connection sock

The complete code is at http://pastie.org/109= 71189 .

But i= t doesn't seem to work. The problems are:
- nothing is= printed on stdout
- when I open 2 connections, the se= cond can only be closed after the first has been closed.

In the mean time I've discovered Lw= t_unix, but before looking at it, I'd like to understand what's wrong in my= current code. Can you spot errors in the code? General advice is also welc= ome!

Thanks
=

Raphael




=

--

= --Apple-Mail=_C8ED71A8-3690-4149-BDA7-54ACF0044951--