Re: [MLton] Multithreading issue when using FFI with C/C++
Matthew Fluet <[email protected]> Wed, 9 Mar 2022 10:00:09 -0500
| Newsgroups | gmane.comp.lang.ml.mlton.devel |
|---|---|
| Message-ID | <CAMrhFL7EN8jaTfAFSPMY6JeuhEZ-Tn9vFGp_s=eDe404Rf_X5Q@mail.gmail.com> |
--===============5206239793893434773== Content-Type: multipart/alternative; boundary="0000000000003a2eb705d9ca5bba" --0000000000003a2eb705d9ca5bba Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable This would be the expected behavior, because neither the MLton runtime nor the MLton compiled mutator code is thread safe. The `libtest_open(argc, argv)` initializes the (shared) heap and runtime system, which has a significant amount of shared global state. Each (parallel) invocation of `ffi_func` will be accessing and mutating that shared state, leading to undefined behavior. You could protect the invocations of `ffi_func` with a global lock on the C++ side, but that would only be beneficial if there are very few concurrent invocations of `ffi_func`. If you are hoping to obtain some parallel speedup with a significant portion of the computation being done on the SML-side, then I'm afraid that MLton will not suffice for this purpose. You might check out the MaPLe project (https://github.com/MPLLang= ), which is a Parallel ML based on MLton. Though, I do not believe that it supports exporting SML functions to C/C++. On Tue, Mar 8, 2022 at 9:25 PM Weiqi Sun <[email protected]> wrote: > Hi, > > I have some sml code that I want to export to C or C++ using the mlton FF= I > feature. However, I encountered an issue when calling the exported sml > function from C/C++ in a multithreading environment. I simplified the iss= ue > as the following: > > I export a dummy sml function called ffi_func that always returns an > integer 1 in =E2=80=9Clibtest.sml=E2=80=9D: > > val f =3D _export "ffi_func": (unit -> int) -> unit; > val _ =3D f(fn () =3D> 1); > > Then I compiled it to an archive named libtest.a and export a header file > test_ffi.h using the following command: > > mlton -default-ann 'allowFFI true' -export-header test_ffi.h -format arch= ive -libname libtest libtest.sml > > With the compiled archive, I can call the ffi_func function in C code > =E2=80=9Cmain.c=E2=80=9D. But when I call it inside threading, it throws = a segmentation > fault. > > #include <stdio.h> > #include <pthread.h> > #include "test_ffi.h" > > void* callOut(void *thread_id) { > int *myid =3D (int *)thread_id; > for (int i =3D 0; i < 100; ++i) { > int rc =3D ffi_func(); > printf("call out: %d - %d - %d\n", *myid, i, rc); > } > return NULL; > } > > void multiRun(int n) { > printf("num thread: %d\n", n); > > pthread_t thread[n]; > int thread_num[n]; > for (int i =3D 0; i < n; ++i) { > thread_num[i] =3D i; > pthread_create(&thread[i], NULL, callOut, (void *)&thread_num[i])= ; > } > > for (int i =3D 0; i < n; ++i) { > pthread_join(thread[i], NULL); > } > } > > int main(int argc, const char** argv) { > libtest_open(argc, argv); > > int n =3D *argv[1] - '0'; > multiRun(n); > > libtest_close(); > } > > The code is compiled by: > > gcc -o test_c main.c -L. -ltest -lpthread > > If I run test_c with only one thread, it works well. But if I use more > than one thread, I got segmentation fault. And different runs give > different error messages. For example, by running ./test_c 3 multiple > times, I could get the following error messages > > unhandled exception: Option > MLton bug: Mlton.Exit.halt > Please send a bug report to [email protected] > Thread.atomicSwitch didn't set r. > > zsh: segmentation fault ./test_c 3 > > Or > > unhandled exception: Fail8 > Thread.atomicSwitch didn't set r. > MLton bug: MLton.Exit.halt > Please send a bug report to [email protected]. > > zsh: bus error ./test_c 3 > > I tested this with both MLton 20201002 and MLton 20210117 and they give > the same errors. And this problem appears on both Mac and Linux. > > Any advice will be appreciated. > > Thanks, > Weiqi > > -- > You received this message because you are subscribed to the Google Groups > "MLton" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > _______________________________________________ > MLton-devel mailing list > [email protected]; [email protected] > https://lists.sourceforge.net/lists/listinfo/mlton-devel > --0000000000003a2eb705d9ca5bba Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div class=3D"gmail_default" style=3D"font-family:arial,sa= ns-serif;font-size:large">This would be the expected behavior, because neit= her the MLton runtime nor the MLton compiled mutator code is thread safe.= =C2=A0 The `libtest_open(argc, argv)` initializes the (shared) heap and run= time system, which has a significant amount of shared global state.=C2=A0 E= ach (parallel) invocation of `ffi_func` will be accessing and mutating that= shared state, leading to undefined behavior.</div><div class=3D"gmail_defa= ult" style=3D"font-family:arial,sans-serif;font-size:large">You could prote= ct the invocations of `ffi_func` with a global lock on the C++ side, but th= at would only be beneficial if there are very few concurrent invocations of= `ffi_func`.=C2=A0 If you are hoping to obtain some parallel speedup with a= significant portion of the computation being done on the SML-side, then I&= #39;m afraid that MLton will not suffice for this purpose.=C2=A0 You might = check out the MaPLe project (<a href=3D"https://github.com/MPLLang">https:/= /github.com/MPLLang</a>), which is a Parallel ML based on MLton.=C2=A0 Thou= gh, I do not believe that it supports exporting SML functions to C/C++.</di= v><div class=3D"gmail_default" style=3D"font-family:arial,sans-serif;font-s= ize:large"><br></div></div><br><div class=3D"gmail_quote"><div dir=3D"ltr" = class=3D"gmail_attr">On Tue, Mar 8, 2022 at 9:25 PM Weiqi Sun <<a href= =3D"mailto:[email protected]">[email protected]</a>> wrote:<br></div><= blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l= eft:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><p s= tyle=3D"margin:0px 0px 1.2em">Hi,</p><p style=3D"margin:0px 0px 1.2em">I ha= ve some sml code that I want to export to C or C++ using the mlton FFI feat= ure. However, I encountered an issue when calling the exported sml function= from C/C++ in a multithreading environment. I simplified the issue as the = following:</p> <p style=3D"margin:0px 0px 1.2em">I export a dummy sml function called <cod= e style=3D"font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monosp= ace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px sol= id rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;dis= play:inline">ffi_func</code> that always returns an integer <code style=3D"= font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:= 0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,= 234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline= ">1</code> in =E2=80=9Clibtest.sml=E2=80=9D:</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">val= f =3D _export "ffi_func": (unit -> int) -> unit; val _ =3D f(fn () =3D> 1); </code></pre><p style=3D"margin:0px 0px 1.2em">Then I compiled it to an arc= hive named <code style=3D"font-size:0.85em;font-family:Consolas,Inconsolata= ,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap= ;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border= -radius:3px;display:inline">libtest.a</code> and export a header file <code= style=3D"font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospa= ce;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px soli= d rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;disp= lay:inline">test_ffi.h</code> using the following command:</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">mlt= on -default-ann 'allowFFI true' -export-header test_ffi.h -format a= rchive -libname libtest libtest.sml </code></pre><p style=3D"margin:0px 0px 1.2em">With the compiled archive, I= can call the <code style=3D"font-size:0.85em;font-family:Consolas,Inconsol= ata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-w= rap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);bor= der-radius:3px;display:inline">ffi_func</code> function in C code =E2=80=9C= main.c=E2=80=9D. But when I call it inside threading, it throws a segmentat= ion fault.</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">#in= clude <stdio.h> #include <pthread.h> #include "test_ffi.h" void* callOut(void *thread_id) { int *myid =3D (int *)thread_id; for (int i =3D 0; i < 100; ++i) { int rc =3D ffi_func(); printf("call out: %d - %d - %d\n", *myid, i, rc); } return NULL; } void multiRun(int n) { printf("num thread: %d\n", n); pthread_t thread[n]; int thread_num[n]; for (int i =3D 0; i < n; ++i) { thread_num[i] =3D i; pthread_create(&thread[i], NULL, callOut, (void *)&thread_n= um[i]); } for (int i =3D 0; i < n; ++i) { pthread_join(thread[i], NULL); } } int main(int argc, const char** argv) { libtest_open(argc, argv); int n =3D *argv[1] - '0'; multiRun(n); libtest_close(); } </code></pre><p style=3D"margin:0px 0px 1.2em">The code is compiled by:</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">gcc= -o test_c main.c -L. -ltest -lpthread </code></pre><p style=3D"margin:0px 0px 1.2em">If I run <code style=3D"font= -size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px = 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,= 234);background-color:rgb(248,248,248);border-radius:3px;display:inline">te= st_c</code> with only one thread, it works well. But if I use more than one= thread, I got segmentation fault. And different runs give different error = messages. For example, by running <code style=3D"font-size:0.85em;font-fami= ly:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3= em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:= rgb(248,248,248);border-radius:3px;display:inline">./test_c 3</code> multip= le times, I could get the following error messages</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">unh= andled exception: Option MLton bug: Mlton.Exit.halt Please send a bug report to <a href=3D"mailto:[email protected]" target=3D"_b= lank">[email protected]</a> Thread.atomicSwitch didn't set r. zsh: segmentation fault ./test_c 3 </code></pre><p style=3D"margin:0px 0px 1.2em">Or</p> <pre style=3D"font-family:Consolas,Inconsolata,Courier,monospace;font-size:= 1em;line-height:1.2em;margin:1.2em 0px"><code style=3D"font-size:0.85em;fon= t-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;backgroun= d-color:rgb(248,248,248);white-space:pre-wrap;overflow:auto;border-radius:3= px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block">unh= andled exception: Fail8 Thread.atomicSwitch didn't set r. MLton bug: MLton.Exit.halt Please send a bug report to <a href=3D"mailto:[email protected]" target=3D"_b= lank">[email protected]</a>. zsh: bus error ./test_c 3 </code></pre><p style=3D"margin:0px 0px 1.2em">I tested this with both MLto= n 20201002 and MLton 20210117 and they give the same errors. And this probl= em appears on both Mac and Linux.</p> <p style=3D"margin:0px 0px 1.2em">Any advice will be appreciated.</p> <p style=3D"margin:0px 0px 1.2em">Thanks,<br>Weiqi</p> <div title=3D"MDH:PGRpdiBpZD0iZ21haWwtOjE5aiIgY2xhc3M9ImdtYWlsLUFyIGdtYWlsL= UF1IGdtYWlsLUFvIj48 ZGl2IGlkPSJnbWFpbC06MTlmIiBjbGFzcz0iZ21haWwtQW0gZ21haWwtQWwgZWRpdGFibGUgZ21= h aWwtTFctYXZmIGdtYWlsLXRTLXRXIGdtYWlsLXRTLXRZIiBhcmlhLWxhYmVsPSJNZXNzYWdlIEJ= v ZHkiIHJvbGU9InRleHRib3giIGFyaWEtbXVsdGlsaW5lPSJ0cnVlIiB0YWJpbmRleD0iMSIgc3R= 5 bGU9ImRpcmVjdGlvbjogbHRyOyBtaW4taGVpZ2h0OiAzMzZweDsiPjxkaXYgaWQ9ImdtYWlsLTp= 4 cCIgY2xhc3M9ImdtYWlsLUFyIGdtYWlsLUF1IGdtYWlsLUFvIj48ZGl2IGlkPSJnbWFpbC06eHQ= i IGNsYXNzPSJnbWFpbC1BbSBnbWFpbC1BbCBlZGl0YWJsZSBnbWFpbC1MVy1hdmYgZ21haWwtdFM= t dFcgZ21haWwtdFMtdFkiIGFyaWEtbGFiZWw9Ik1lc3NhZ2UgQm9keSIgYXJpYS1tdWx0aWxpbmU= 9 InRydWUiIHRhYmluZGV4PSIxIiBzdHlsZT0iZGlyZWN0aW9uOiBsdHI7IG1pbi1oZWlnaHQ6IDM= z NnB4OyI+SGksPGRpdj48YnI+PC9kaXY+PGRpdj5JIGhhdmUgc29tZSA8c3BhbiB6ZXVtNGMxND0= i UFJfMV8wIiBkYXRhLWRkbndhYj0iUFJfMV8wIiBhcmlhLWludmFsaWQ9ImdyYW1tYXIiIGNsYXN= z PSJMbSBuZyI+c21sPC9zcGFuPiBjb2RlIHRoYXQgSSB3YW50IHRvIGV4cG9ydCB0byBDIG9yIEM= r KyB1c2luZyB0aGUgbWx0b24gRkZJIGZlYXR1cmUuIEhvd2V2ZXIsIEkgZW5jb3VudGVyZWQmbmJ= z cDthbiBpc3N1ZSB3aGVuIGNhbGxpbmcgdGhlIGV4cG9ydGVkIHNtbCBmdW5jdGlvbiBmcm9tIEM= v QysrIDxzcGFuIHpldW00YzE0PSJQUl8yXzAiIGRhdGEtZGRud2FiPSJQUl8yXzAiIGFyaWEtaW5= 2 YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj5pbiBtdWx0aXRocmVhZGluZzwvc3Bhbj4gZW5= 2 aXJvbm1lbnQuIEkgc2ltcGxpZmllZCZuYnNwO3RoZSBpc3N1ZSBhcyB0aGUgZm9sbG93aW5nOjw= v ZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+SSBleHBvcnQgYSBkdW1teSBzbWwgZnVuY3Rpb24gY2F= s bGVkIGBmZmlfZnVuY2AgdGhhdCBhbHdheSByZXR1cm4gYW4gaW50ZWdlciBgMWAgaW4gImxpYnR= l c3Quc21sIjo8L2Rpdj48ZGl2PmBgYDwvZGl2PjxkaXY+dmFsIGYgPSBfZXhwb3J0ICJmZmlfZnV= u YyI6ICh1bml0IC0mZ3Q7IGludCkgLSZndDsgdW5pdDs8L2Rpdj48ZGl2PnZhbCBfID0gZihmbiA= o KSA9Jmd0OyAxKTs8L2Rpdj48ZGl2PmBgYDwvZGl2PjxkaXY+VGhlbiBJIGNvbXBpbGVkIGl0IHR= v IGFuIGFyY2hpdmUgbmFtZWQgYGxpYnRlc3QuYWAgYW5kIGV4cG9ydCBhIGhlYWRlciBmaWxlIGB= 0 ZXN0X2ZmaS5oYCB1c2luZyB0aGUgZm9sbG93aW5nIGNvbW1hbmQ6PC9kaXY+PGRpdj5gYGA8L2R= p dj48ZGl2Pm1sdG9uIC1kZWZhdWx0LWFubiAnYWxsb3dGRkkgdHJ1ZScgLWV4cG9ydC1oZWFkZXI= g dGVzdF9mZmkuaCAtZm9ybWF0IGFyY2hpdmUgLWxpYm5hbWUgbGlidGVzdCBsaWJ0ZXN0LnNtbDw= v ZGl2PjxkaXY+YGBgPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5XaXRoIHRoZSBjb21waWxlZCB= h cmNoaXZlLCBJIGNhbiBjYWxsIHRoZSBgZmZpX2Z1bmNgIGZ1bmN0aW9uIGluIEMgY29kZSAibWF= p bi5jIi4gQnV0IHdoZW4gSSA8c3BhbiB6ZXVtNGMxND0iUFJfMzJfMCIgZGF0YS1kZG53YWI9IlB= S XzMyXzAiIGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj5jYWxsaW5nPC9zcGF= u PiBpdCBpbnNpZGUgdGhyZWFkaW5nLCBpdCA8c3BhbiB6ZXVtNGMxND0iUFJfMzNfMCIgZGF0YS1= k ZG53YWI9IlBSXzMzXzAiIGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj50aHJ= v d3Mgc2VnbWVudGF0aW9uPC9zcGFuPiBmYXVsdC48L2Rpdj48ZGl2PmBgYDwvZGl2PjxkaXY+I2l= u Y2x1ZGUgJmx0O3N0ZGlvLmgmZ3Q7PC9kaXY+PGRpdj4jaW5jbHVkZSAmbHQ7cHRocmVhZC5oJmd= 0 OzwvZGl2PjxkaXY+I2luY2x1ZGUgInRlc3RfZmZpLmgiPC9kaXY+PGRpdj48YnI+PC9kaXY+PGR= p dj52b2lkKiBjYWxsT3V0KHZvaWQgKnRocmVhZF9pZCkgezwvZGl2PjxkaXY+Jm5ic3A7ICZuYnN= w OyBpbnQgKm15aWQgPSAoaW50ICopdGhyZWFkX2lkOzwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyB= m b3IgKGludCBpID0gMDsgaSAmbHQ7IDEwMDsmbmJzcDsrK2kpIHs8L2Rpdj48ZGl2PiZuYnNwOyA= m bmJzcDsgJm5ic3A7ICZuYnNwOyBpbnQgcmMgPSBmZmlfZnVuYygpOzwvZGl2PjxkaXY+Jm5ic3A= 7 ICZuYnNwOyAmbmJzcDsgJm5ic3A7IHByaW50ZigiY2FsbCBvdXQ6ICVkIC0gJWQgLSAlZFxuIiw= g Km15aWQsIGksIHJjKTs8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgfTwvZGl2PjxkaXY+Jm5ic3A= 7 ICZuYnNwOyByZXR1cm4gTlVMTDs8L2Rpdj48ZGl2Pn08L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl= 2 PnZvaWQgbXVsdGlSdW4oaW50IG4pIHs8L2Rpdj48ZGl2PiZuYnNwOyAmbmJzcDsgcHJpbnRmKCJ= u dW0gdGhyZWFkOiAlZFxuIiwgbik7PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4mbmJzcDsgJm5= i c3A7IHB0aHJlYWRfdCB0aHJlYWRbbl07PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7IGludCB0aHJ= l YWRfbnVtW25dOzwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyBmb3IgKGludCBpID0gMDsgaSAmbHQ= 7 IG47Jm5ic3A7KytpKSB7PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgdGh= y ZWFkX251bVtpXSA9IGk7PC9kaXY+PGRpdj4mbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgcHR= o cmVhZF9jcmVhdGUoPHNwYW4gemV1bTRjMTQ9IlBSXzVfMCIgZGF0YS1kZG53YWI9IlBSXzVfMCI= g YXJpYS1pbnZhbGlkPSJzcGVsbGluZyIgY2xhc3M9IkxJIG5nIj4mYW1wO3RocmVhZDwvc3Bhbj5= b aV0sIE5VTEwsIGNhbGxPdXQsICh2b2lkICopJmFtcDt0aHJlYWRfbnVtW2ldKTs8L2Rpdj48ZGl= 2 PiZuYnNwOyAmbmJzcDsgfTwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyB= m b3IgKGludCBpID0gMDsgaSAmbHQ7IG47Jm5ic3A7KytpKSB7PC9kaXY+PGRpdj4mbmJzcDsgJm5= i c3A7ICZuYnNwOyAmbmJzcDsgcHRocmVhZF9qb2luKHRocmVhZFtpXSwgTlVMTCk7PC9kaXY+PGR= p dj4mbmJzcDsgJm5ic3A7IH08L2Rpdj48ZGl2Pn08L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pml= u dCBtYWluKGludCBhcmdjLCBjb25zdCBjaGFyKiogYXJndikgezwvZGl2PjxkaXY+Jm5ic3A7ICZ= u YnNwOyBsaWJ0ZXN0X29wZW4oYXJnYywgYXJndik7PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4= m bmJzcDsgJm5ic3A7IGludCBuID0gKmFyZ3ZbMV0gLSAnMCc7PC9kaXY+PGRpdj4mbmJzcDsgJm5= i c3A7IG11bHRpUnVuKG4pOzwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+Jm5ic3A7ICZuYnNwOyB= s aWJ0ZXN0X2Nsb3NlKCk7PC9kaXY+PGRpdj59PC9kaXY+PGRpdj5gYGA8L2Rpdj48ZGl2Pjxicj4= 8 L2Rpdj48ZGl2PlRoZSBjb2RlIGlzIGNvbXBpbGVkIGJ5Ojxicj5gYGA8L2Rpdj48ZGl2PmdjYyA= t byB0ZXN0X2MgbWFpbi5jIC1MLiAtPHNwYW4gemV1bTRjMTQ9IlBSXzZfMCIgZGF0YS1kZG53YWI= 9 IlBSXzZfMCIgYXJpYS1pbnZhbGlkPSJzcGVsbGluZyIgY2xhc3M9IkxJIG5nIj5sdGVzdDwvc3B= h bj4mbmJzcDstbHB0aHJlYWQ8L2Rpdj48ZGl2PmBgYDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY= + SWYgSSBydW4gYHRlc3RfY2Agd2l0aCBvbmx5IG9uZSB0aHJlYWQsIGl0IHdvcmtzIHdlbGwuIEJ= 1 dCBpZiBJIHVzZSBtb3JlIHRoYW4gb25lIHRocmVhZCwgSSA8c3BhbiB6ZXVtNGMxND0iUFJfN18= w IiBkYXRhLWRkbndhYj0iUFJfN18wIiBhcmlhLWludmFsaWQ9ImdyYW1tYXIiIGNsYXNzPSJMbSB= u ZyI+Z290PC9zcGFuPiBzZWdtZW50YXRpb24gZmF1bHQuIEFuZCBkaWZmZXJlbnQgcnVucyBnaXZ= l IGRpZmZlcmVudCBlcnJvciBtZXNzYWdlcy4gRm9yIGV4YW1wbGUsIGJ5IHJ1bm5pbmcgYC4vdGV= z dF9jIDNgIG11bHRpcGxlIHRpbWVzLCBJIGNvdWxkIGdldCB0aGUgZm9sbG93aW5nIGVycm9yIG1= l c3NhZ2VzPC9kaXY+PGRpdj5gYGA8L2Rpdj48ZGl2PnVuaGFuZGxlZCBleGNlcHRpb246IE9wdGl= v bjwvZGl2PjxkaXY+TUx0b24gYnVnOiA8c3BhbiB6ZXVtNGMxND0iUFJfOF8wIiBkYXRhLWRkbnd= h Yj0iUFJfOF8wIiBhcmlhLWludmFsaWQ9InNwZWxsaW5nIiBjbGFzcz0iTEkgbmciPk1sdG9uLkV= 4 aXQuaGFsdDwvc3Bhbj48L2Rpdj48ZGl2PlBsZWFzZSBzZW5kIGEgYnVnIHJlcG9ydCB0byBNTHR= v bkBtbHRvbi5vcmc8L2Rpdj48ZGl2PlRocmVhZC5hdG9taWNTd2l0Y2ggZGlkbid0IHNldCByLjw= v ZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+enNoOiBzZWdtZW50YXRpb24gZmF1bHQgLi90ZXN0X2M= g MzwvZGl2PjxkaXY+YGBgPC9kaXY+PGRpdj5PcjwvZGl2PjxkaXY+YGBgPC9kaXY+PGRpdj51bmh= h bmRsZWQgZXhjZXB0aW9uOiBGYWlsODwvZGl2PjxkaXY+VGhyZWFkLmF0b21pY1N3aXRjaCBkaWR= u J3Qgc2V0IHIuPC9kaXY+PGRpdj5NTHRvbiBidWc6IE1MdG9uLkV4aXQuaGFsdDwvZGl2PjxkaXY= + UGxlYXNlIHNlbmQgYSBidWcgcmVwb3J0IHRvIE1MdG9uQG1sdG9uLm9yZy48L2Rpdj48ZGl2Pjx= i cj48L2Rpdj48ZGl2PnpzaDogYnVzIGVycm9yIC4vdGVzdF9jIDM8L2Rpdj48ZGl2PmBgYDwvZGl= 2 PjxkaXY+PGJyPjwvZGl2PjxkaXY+SSB0ZXN0ZWQgdGhpcyB3aXRoIGJvdGggTUx0b24mbmJzcDs= y MDIwMTAwMiBhbmQgTUx0b24gMjAyMTAxMTcgYW5kIHRoZXkgZ2l2ZSB0aGUgc2FtZSBlcnJvcnM= u IEFuZCB0aGlzIHByb2JsZW0gYXBwZWFycyBvbiBib3RoIE1hYyBhbmQgTGludXguPC9kaXY+PGR= p dj48YnI+PC9kaXY+PGRpdj5BbnkgYWR2aWNlIHdpbGwgYmUgYXBwcmVjaWF0ZWQuPC9kaXY+PGR= p dj48YnI+PC9kaXY+PGRpdj5UaGFua3MsPC9kaXY+PGRpdj5XZWlxaTwvZGl2PjwvZGl2PjwvZGl= 2 PjwvZGl2PjwvZGl2Pg=3D=3D" style=3D"height:0px;width:0px;max-height:0px;max-= width:0px;overflow:hidden;font-size:0em;padding:0px;margin:0px"></div></div= ></div> <p></p> -- <br> You received this message because you are subscribed to the Google Groups &= quot;MLton" group.<br> To unsubscribe from this group and stop receiving emails from it, send an e= mail to <a href=3D"mailto:[email protected]" target=3D"_blank">ml= [email protected]</a>.<br> _______________________________________________<br> MLton-devel mailing list<br> <a href=3D"mailto:[email protected]" target=3D"_blank">MLto= [email protected]</a>; <a href=3D"mailto:[email protected]"= target=3D"_blank">[email protected]</a><br> <a href=3D"https://lists.sourceforge.net/lists/listinfo/mlton-devel" rel=3D= "noreferrer" target=3D"_blank">https://lists.sourceforge.net/lists/listinfo= /mlton-devel</a><br> </blockquote></div> --0000000000003a2eb705d9ca5bba-- --===============5206239793893434773== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline --===============5206239793893434773== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ MLton-devel mailing list [email protected]; [email protected] https://lists.sourceforge.net/lists/listinfo/mlton-devel --===============5206239793893434773==--