* crash under macos x but not win32
@ 2007-04-10 0:19 Jeffrey Loren Shaw
2007-04-10 1:07 ` [Caml-list] " Jacques Garrigue
0 siblings, 1 reply; 7+ messages in thread
From: Jeffrey Loren Shaw @ 2007-04-10 0:19 UTC (permalink / raw)
To: caml-list
The following works as intended in Win32 (the ui counts slowly from 0 to 5),
but crashes in Mac OS X with "Bus Error". I'm running ocaml 3.09.3 installed
with macports. For windows I used the Ocaml 3.09.3 MinGW binary
distribution.
(* looptest.ml *)
open Tk
let testone () =
let top = openTk () in
let l = Label.create top in
let loopfun () =
ignore
(
Thread.create
(fun () ->
for i=0 to 5 do
Thread.delay 1.;
Label.configure ~text:(string_of_int i) l
done
)
()
)
in
let b = Button.create ~text:"Run the test" ~command:loopfun top in
pack [l];
pack [b];
mainLoop ();;
testone ()
(* end looptest.ml *)
runs with: ocaml -I +labltk -I +threads unix.cma threads.cma labltk.cma
looptest.ml
Any ideas? Perhaps the following information will help, I don't know.
Thread 3 Crashed:
0 com.tcltk.tklibrary 0x9acead88 Tk_FreeGC + 30
1 com.tcltk.tklibrary 0x9acbe64d TkButtonWorldChanged + 117
2 com.tcltk.tklibrary 0x9acbed53 ConfigureButton + 1400
3 com.tcltk.tklibrary 0x9acbf68f ButtonWidgetObjCmd + 416
4 com.tcltk.tcllibrary 0x9ac2b2c3 TclInvokeObjectCommand + 264
5 dlllabltk.so 0x000e294b camltk_tcl_direct_eval + 623
6 ocamlrun 0x00012ba3 caml_interprete + 6262
7 ocamlrun 0x0000e0ba caml_callbackN_exn + 185
8 ocamlrun 0x0000e103 caml_callback_exn + 38
9 dllthreads.so 0x000d73e8 caml_thread_start + 80
10 libSystem.B.dylib 0x90024147 _pthread_body + 84
Thread 3 crashed with X86 Thread State (32-bit):
eax: 0x00000000 ebx: 0x9acead78 ecx: 0x0c5a9048 edx: 0x00000015
edi: 0x01668608 esi: 0x00000000 ebp: 0xb0203838 esp: 0xb0203810
ss: 0x0000001f efl: 0x00010286 eip: 0x9acead88 cs: 0x00000017
ds: 0x0000001f es: 0x0000001f fs: 0x00000000 gs: 0x00000037
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 0:19 crash under macos x but not win32 Jeffrey Loren Shaw
@ 2007-04-10 1:07 ` Jacques Garrigue
2007-04-10 2:08 ` skaller
2007-04-10 3:56 ` Jeffrey Loren Shaw
0 siblings, 2 replies; 7+ messages in thread
From: Jacques Garrigue @ 2007-04-10 1:07 UTC (permalink / raw)
To: shawjef3; +Cc: caml-list
From: "Jeffrey Loren Shaw" <shawjef3@msu.edu>
> The following works as intended in Win32 (the ui counts slowly from 0 to 5),
> but crashes in Mac OS X with "Bus Error". I'm running ocaml 3.09.3 installed
> with macports. For windows I used the Ocaml 3.09.3 MinGW binary
> distribution.
>
> (* looptest.ml *)
>
> open Tk
>
> let testone () =
> let top = openTk () in
> let l = Label.create top in
> let loopfun () =
> ignore
> (
> Thread.create
> (fun () ->
> for i=0 to 5 do
> Thread.delay 1.;
> Label.configure ~text:(string_of_int i) l
> done
> )
> ()
> )
> in
> let b = Button.create ~text:"Run the test" ~command:loopfun top in
> pack [l];
> pack [b];
> mainLoop ();;
>
> testone ()
>
> (* end looptest.ml *)
>
> runs with: ocaml -I +labltk -I +threads unix.cma threads.cma labltk.cma
> looptest.ml
The Aqua version of Tk is notoriously unstable when used with labltk,
but this doesn't seem to be the problem here. Rather, it appears not
to be reentrant (or rather not callable from several threads.) By the
way I am surprised you have no problem under Win32, which often has
reentrance problems too.
Anyway, there is a Tkthread module to solve these reentrance problems.
Here is the code using it, adding "sync" and "async" where needed.
open Tk
open Tkthread
let tk = start () (* Calls openTk and mainLoop in a new thread *)
let testone () =
Thread.delay 0.1; (* wait for initialization *)
let l = sync Label.create top in
let loopfun () =
ignore
(
Thread.create
(fun () ->
for i=0 to 5 do
Thread.delay 1.;
async (Label.configure ~text:(string_of_int i)) l
done
)
()
)
in
let b = sync (Button.create ~text:"Run the test" ~command:loopfun) top in
async pack [l];
async pack [b];
Thread.join tk;; (* wait for mainLoop to finish *)
testone ()
And start it with
ocaml -I +labltk -I +threads unix.cma threads.cma labltk.cma tkthread.cmo looptest2.ml
The wait for initialization part is kind of hacky, as the thread start
function was rather intended for interactive use, but it should be
portable enough.
Jacques Garrigue
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 1:07 ` [Caml-list] " Jacques Garrigue
@ 2007-04-10 2:08 ` skaller
2007-04-10 2:41 ` Jacques Garrigue
2007-04-10 3:56 ` Jeffrey Loren Shaw
1 sibling, 1 reply; 7+ messages in thread
From: skaller @ 2007-04-10 2:08 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: shawjef3, caml-list
On Tue, 2007-04-10 at 10:07 +0900, Jacques Garrigue wrote:
> From: "Jeffrey Loren Shaw" <shawjef3@msu.edu>
> Rather, it appears not
> to be reentrant (or rather not callable from several threads.) By the
> way I am surprised you have no problem under Win32, which often has
> reentrance problems too.
Tcl is re-entant since version 8. Tk is not and never will be.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 2:08 ` skaller
@ 2007-04-10 2:41 ` Jacques Garrigue
0 siblings, 0 replies; 7+ messages in thread
From: Jacques Garrigue @ 2007-04-10 2:41 UTC (permalink / raw)
To: skaller; +Cc: shawjef3, caml-list
From: skaller <skaller@users.sourceforge.net>
> On Tue, 2007-04-10 at 10:07 +0900, Jacques Garrigue wrote:
> > From: "Jeffrey Loren Shaw" <shawjef3@msu.edu>
>
> > Rather, it appears not
> > to be reentrant (or rather not callable from several threads.) By the
> > way I am surprised you have no problem under Win32, which often has
> > reentrance problems too.
>
> Tcl is re-entant since version 8. Tk is not and never will be.
Actually this is not the problem here, as ocaml does not need full
reentrance (ability to call the library after preemption), but just a
weaker form (ability to call the library from any thread, after
control was given back to the ocaml process). This is because only one
ocaml thread runs at any time, and only when the control is on the
caml side. So I believe the problem is at a lower level, either in the
system's graphics libraries (I'm no OSX specialist), or in the
specifics of the Tk/Aqua implementation. For instance, on windows, GDI
functions must always be called from the same thread or you get an
error.
Jacques Garrigue
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 1:07 ` [Caml-list] " Jacques Garrigue
2007-04-10 2:08 ` skaller
@ 2007-04-10 3:56 ` Jeffrey Loren Shaw
2007-04-10 4:15 ` Jacques Garrigue
1 sibling, 1 reply; 7+ messages in thread
From: Jeffrey Loren Shaw @ 2007-04-10 3:56 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: caml-list
Jacques Garrigue,
Thanks for your reply! Inspired by your use of Timer.set in Tkthreads, I
decided to use a library I keep handy for queued communication between
threads. Using it frees me of having to type sync, async, etc a lot. The
only major improvement now would be to make it so that you don't have to
poll the queue. I don't know how to do that right now.
type 'a qm =
{q : 'a Queue.t;
m : Mutex.t;
c : Condition.t;
}
let createqm () =
{q = Queue.create ();
m = Mutex.create ();
c = Condition.create ();
}
let addtoq qm a =
Mutex.lock qm.m;
Queue.push a qm.q;
Condition.signal qm.c;
Mutex.unlock qm.m
let getfromq_noblock qm =
if Mutex.try_lock qm.m then
if Queue.is_empty qm.q then
(
Mutex.unlock qm.m;
None
)
else
let r = Some (Queue.pop qm.q) in
Mutex.unlock qm.m;
r
else
None
let testthree () =
let top = openTk () in
let l = Label.create top in
let lconfig s () = Label.configure ~text:s l in
let qm = createqm () in
let loopfun () =
ignore
(
Thread.create
(fun () ->
for i=0 to 5 do
Thread.delay 1.;
addtoq qm (lconfig (string_of_int i))
done
)
()
)
in
let b = Button.create ~text:"Run the test" ~command:loopfun top in
let rec watcher () =
Timer.set
~ms:10
~callback:
(fun () ->
match getfromq_noblock qm with
None -> watcher ()
| Some f -> f (); watcher ()
)
in
watcher ();
pack [l];
pack [b];
mainLoop ();
exit 0;;
testthree ()
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 3:56 ` Jeffrey Loren Shaw
@ 2007-04-10 4:15 ` Jacques Garrigue
2007-04-10 5:52 ` skaller
0 siblings, 1 reply; 7+ messages in thread
From: Jacques Garrigue @ 2007-04-10 4:15 UTC (permalink / raw)
To: shawjef3; +Cc: caml-list
From: "Jeffrey Loren Shaw" <shawjef3@msu.edu>
> Thanks for your reply! Inspired by your use of Timer.set in Tkthreads, I
> decided to use a library I keep handy for queued communication between
> threads. Using it frees me of having to type sync, async, etc a lot. The
> only major improvement now would be to make it so that you don't have to
> poll the queue. I don't know how to do that right now.
There may be a misunderstanding due to my translation.
You don't have to write a sync or async for each and every Tk function
call. In your example below, you could write
open Tkthread
let tk = start ()
let testthree () =
let top = openTk () in
let l = Label.create top in
let lconfig s () =
let qm = createqm () in
let loopfun () =
ignore
(
Thread.create
(fun () ->
for i=0 to 5 do
Thread.delay 1.;
async (Label.configure ~text:(string_of_int i)) l
done
)
()
)
in
let b = Button.create ~text:"Run the test" ~command:loopfun top in
pack [l];
pack [b]
let () =
async testthree ();
Thread.join tk;
exit 0
By the way, the polling is needed in order to have threads running
while using the Tk main loop. One could also do the opposite, polling
for Tk events while running an ocaml main loop...
Jacques Garrigue
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] crash under macos x but not win32
2007-04-10 4:15 ` Jacques Garrigue
@ 2007-04-10 5:52 ` skaller
0 siblings, 0 replies; 7+ messages in thread
From: skaller @ 2007-04-10 5:52 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: shawjef3, caml-list
On Tue, 2007-04-10 at 13:15 +0900, Jacques Garrigue wrote:
> By the way, the polling is needed in order to have threads running
> while using the Tk main loop. One could also do the opposite, polling
> for Tk events while running an ocaml main loop...
This the classic control inversion problem, when two top level
architectures both demand to run the event loop. From memory,
Tcl is very good in this area, since it is actually designed to
support event loop merging, which of course was dictated by the
need to handle GUIs as an extension.
More recent offerings such as Gtk seem to have taken a massive
backwards step.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2007-04-10 5:52 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-10 0:19 crash under macos x but not win32 Jeffrey Loren Shaw
2007-04-10 1:07 ` [Caml-list] " Jacques Garrigue
2007-04-10 2:08 ` skaller
2007-04-10 2:41 ` Jacques Garrigue
2007-04-10 3:56 ` Jeffrey Loren Shaw
2007-04-10 4:15 ` Jacques Garrigue
2007-04-10 5:52 ` skaller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox