|
From: <tim...@en...> - 2005-06-24 16:44:55
|
Hello ! I keep working on the wxwidgets terminal, and I am now facing a=20 difficult problem. When there are errors on a command line, gnuplot uses its functions=20 int_error(token, string) to inform the user and stop parsing the command=20 line. This function prints an error message and then calls=20 bail_to_command_line() which is simply a wrapper for the standard=20 longjmp(env) function. This is similar to "goto", and puts the program=20 in its initial state by restoring the registers set in main(). As far as I understand, this would be perfect if I had not to use a=20 separate thread for my terminal. Indeed, I want to send a command from=20 the terminal (through a menu for example) to gnuplot. I use events=20 defined in mouse.c, and more precisely a "command" event (which doesn't=20 seem to be used very often, or maybe in OS/2 only). The do_event(event)=20 is executed in my gui thread. When an error appears on the command, we=20 obtain a longjump which is invalid for *this* gui thread... and it ends=20 with a segmentation fault. I can't simply delete the longjump, as it is necessary to stop command=20 line parsing. If I do it, gnuplot either seems to enter in a infinite=20 loop or terminante with an other segfault. Of course, there's a solution : avoid any error in commands sent from my=20 terminal. But it's like reinventing the wheel. (These errors can be=20 various : for example, if I write a dialog to "set xlabel", and the user=20 enters forbidden characters; or I want to send a "replot" while it's the=20 "test" command which has opened the terminal, etc.) Another solution would be to build the terminal as a separate process,=20 like x11 or os/2 ones. But I think it's not an optimal design. So I would be pleased if somebody can give me a tip in order to deal=20 with this issue ;-) . On my side, I will look more thoroughly to existing code to see how=20 things are done (by windows gui, os/2 pm, etc. ) Greetings, Timoth=E9e |
|
From: Ethan M. <merritt@u.washington.edu> - 2005-06-24 17:10:12
|
Caveat: I don't really understand how your new terminal type is supposed to work. So maybe I have the wrong end of the stick here... On Friday 24 June 2005 11:45 am, Timoth=C3=A9e Lecomte wrote: >=20 > As far as I understand, this would be perfect if I had not to use a=20 > separate thread for my terminal. Indeed, I want to send a command from=20 > the terminal (through a menu for example) to gnuplot. I use events=20 > defined in mouse.c, and more precisely a "command" event (which doesn't=20 > seem to be used very often, or maybe in OS/2 only). The do_event(event)=20 > is executed in my gui thread. When an error appears on the command, we=20 > obtain a longjump which is invalid for *this* gui thread... and it ends=20 > with a segmentation fault. I would think the proper fix is to re-initialize the longjump at the start of each thread creation. Then if you get an error it will jump to a per-thread error handler and exit the thread cleanly. > Another solution would be to build the terminal as a separate process,=20 > like x11 or os/2 ones. But I think it's not an optimal design. > So I would be pleased if somebody can give me a tip in order to deal=20 > with this issue ;-) . I might understand better if you would briefly describe the flow of control you are trying to achieve. What does the new terminal type do that existing terminals do not handle already? Is the user expected to run gnuplot from a command line, but when 'set term wxwidgets' is selected a=20 separate control window appears? Or does the user run a wrapping program that executes gnuplot underneath with the terminal pre-set to communicate w= ith the wrapping layer? =20 If it's the latter, then I'm not sure you even need a new terminal type. You may be able to use 'set term x11' and direct the output to an embedded panel of the wrapping program (see patchset #1027032). I'm not saying this is the best thing to do, but I point it out as a possibility. =20 =2D-=20 Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: <tim...@en...> - 2005-06-24 18:42:07
|
Ethan Merritt wrote: >Caveat: I don't really understand how your new terminal type is supposed >to work. So maybe I have the wrong end of the stick here... > >On Friday 24 June 2005 11:45 am, Timoth=C3=A9e Lecomte wrote: > =20 > >>As far as I understand, this would be perfect if I had not to use a=20 >>separate thread for my terminal. Indeed, I want to send a command from=20 >>the terminal (through a menu for example) to gnuplot. I use events=20 >>defined in mouse.c, and more precisely a "command" event (which doesn't= =20 >>seem to be used very often, or maybe in OS/2 only). The do_event(event)= =20 >>is executed in my gui thread. When an error appears on the command, we=20 >>obtain a longjump which is invalid for *this* gui thread... and it ends= =20 >>with a segmentation fault. >> =20 >> > >I would think the proper fix is to re-initialize the longjump at the >start of each thread creation. Then if you get an error it will jump >to a per-thread error handler and exit the thread cleanly. > =20 > I have just tried it. The remaining problem is that setjmp/longjmp were=20 designed for C, not C++. In particular, longjmp doesn't do any extra=20 work needed by C++, such as deleting objects. So if I initialize the=20 longjump when creating my terminal thread, it doesn't delete the old=20 window but open a new one when longjmp is used ! However, it does not=20 segfault... So the solution may be to check if another window is opened=20 and destroy it before to continue. That doesn't seem very efficient. >>Another solution would be to build the terminal as a separate process,=20 >>like x11 or os/2 ones. But I think it's not an optimal design. >>So I would be pleased if somebody can give me a tip in order to deal=20 >>with this issue ;-) . >> =20 >> > >I might understand better if you would briefly describe the flow of >control you are trying to achieve. What does the new terminal type do >that existing terminals do not handle already? Is the user expected to = run >gnuplot from a command line, but when 'set term wxwidgets' is selected a= =20 >separate control window appears? Or does the user run a wrapping progr= am >that executes gnuplot underneath with the terminal pre-set to communicat= e with >the wrapping layer? =20 > >If it's the latter, then I'm not sure you even need a new terminal type. >You may be able to use 'set term x11' and direct the output to an embedd= ed >panel of the wrapping program (see patchset #1027032). I'm not saying t= his >is the best thing to do, but I point it out as a possibility. > =20 > I will try to explain briefly. I write a terminal like the x11, postscript, etc. So I use the standard=20 gnuplot interactive command line, type "set terminal wxt" and then any=20 plot command makes the plot window appears, as the x11 terminal works=20 for example. The window is opened in a thread inside gnuplot main=20 process. Thus, your precedent remark is pertinent. I want to implement extra interactivity menus or toolbar. So I want to=20 send commands back to the command interpreter. I do that with do_event=20 which is precisely written for it. Regards Timoth=C3=A9e |
|
From: Ethan M. <merritt@u.washington.edu> - 2005-06-24 19:02:58
|
On Friday 24 June 2005 01:42 pm, Timoth=C3=A9e Lecomte wrote: > Ethan Merritt wrote: >=20 > > > >I would think the proper fix is to re-initialize the longjump at the > >start of each thread creation. Then if you get an error it will jump > >to a per-thread error handler and exit the thread cleanly. > > =20 > > > I have just tried it. The remaining problem is that setjmp/longjmp were=20 > designed for C, not C++. I see. So your new driver is C++ only? That is already a potential problem since the rest of the gnuplot is distinctly not C++ code. I fear it will limit the number of platforms on which your new driver will actually compile and link into gnuplot successfully. We'll find out, I guess. > So if I initialize the =20 > longjump when creating my terminal thread, it doesn't delete the old=20 > window but open a new one when longjmp is used ! However, it does not=20 > segfault... So the solution may be to check if another window is opened=20 > and destroy it before to continue. That doesn't seem very efficient. Can't you do the same thing as the x11 driver? When you send a new plot command the driver looks to see if there is an existing window and if so uses it. If there is no existing window then it opens a new one. See the difference? You check for an old window, but instead of destoying it you just use it explicitly for the new plot also. =2D-=20 Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: <tim...@en...> - 2005-06-24 19:41:18
|
Ethan Merritt wrote: >On Friday 24 June 2005 01:42 pm, Timoth=C3=A9e Lecomte wrote: > =20 > >>Ethan Merritt wrote: >> =20 >> >> The remaining problem is that setjmp/longjmp were=20 >>designed for C, not C++. >> =20 >> >I see. So your new driver is C++ only?=20 > It is C++ only, but until now I have managed to mix C and C++ without=20 problems. I have added a few lines in configure.in (for both c++ and=20 wxwidgets), written my terminal as a common wxt.trm whith C++ functions=20 defined in an external wxt.cpp file. >That is already a potential problem since the rest of the gnuplot is dis= tinctly not C++ code. >I fear it will limit the number of platforms on which your new >driver will actually compile and link into gnuplot successfully. >We'll find out, I guess. > =20 > According to c++ documentation, it should not be a problem (provided we=20 have a c++ compiler for the desired platform ;-). The C and C++ files=20 are compiled by their respective compilers, and then the C++ one link=20 everything. It works at least on my machine. >>So if I initialize the =20 >>longjump when creating my terminal thread, it doesn't delete the old=20 >>window but open a new one when longjmp is used ! However, it does not=20 >>segfault... So the solution may be to check if another window is opened= =20 >>and destroy it before to continue. That doesn't seem very efficient. >> =20 >> > >Can't you do the same thing as the x11 driver? When you send a new >plot command the driver looks to see if there is an existing window and = if >so uses it. If there is no existing window then it opens a new one. >See the difference? You check for an old window, but instead of destoyi= ng >it you just use it explicitly for the new plot also. > =20 > I think that all this setjmp/longjmp stuff makes it difficult. I've=20 tried some combinations, and even if objects are not destroyed, they are=20 not usable ! I can't tell anything to the frame. On the other hand, I wrote things so that when user closes the terminal=20 window, in fact he only hides it, so on next plot it is still available=20 and it is asked to unhide. But setjmp/longjmp are not the same problem=20 unfortunately ! Timoth=C3=A9e Timoth=C3=A9e |
|
From: <tim...@en...> - 2005-06-24 20:09:53
|
Thanks to your different points of view, I finally got it working ! Nigel has the most "C++ friendly" solution, but I think I'm not enough=20 experiences with exceptions to override bail_to_command_line() with them. However, as Ethan and Dave proposed, I can do my own setjump in the=20 thread which is sending the command. As I can't come back from a=20 longjump to my gui thread (because it contains c++ objects), I simply=20 have to use another thread. This "worker thread" has no object, so it is=20 "setjmp - safe". It verifies if it is called from the longjump to avoid=20 sending the command again. This way, I only need to add a test to bail_to_command_line() to call=20 the good longjmp(). I hope you'll find this solution convenient ! Timoth=C3=A9e P.S. : Here's a gift : http://tipote.free.fr/wxt2.png A screenshot of the current state of the terminal |
|
From:
<br...@ph...> - 2005-06-25 08:36:29
|
Ethan Merritt wrote: > I see. So your new driver is C++ only? That is already a potential > problem since the rest of the gnuplot is distinctly not C++ code. > I fear it will limit the number of platforms on which your new > driver will actually compile and link into gnuplot successfully. Not any more than the fact that the desired output system for that driver being C++ already limited it. I.e. if wxWidgets runtime and development support exists on the box, there's nothing to stop a gnuplot build from using them. If there's an actual problem to be caused by this, it'll be that the link of the entire gnuplot will now have to be done with the C++ compiler's linker presets. I.e. we'll pull in the C++ startup code. On less sane platforms, that could indeed cause trouble. |
|
From: Dave D. <dde...@es...> - 2005-06-24 17:25:05
|
Timoth=E9e Lecomte <tim...@en...> writes: > Hello ! > > I keep working on the wxwidgets terminal, and I am now facing a > difficult problem. > > When there are errors on a command line, gnuplot uses its functions > int_error(token, string) to inform the user and stop parsing the > command line. This function prints an error message and then calls > bail_to_command_line() which is simply a wrapper for the standard > longjmp(env) function. This is similar to "goto", and puts the program > in its initial state by restoring the registers set in main(). > It is *currently* "simply a wrapper" for longjmp. A good while ago, I went through replacing lots of explicit longjmp calls with this wrapper, precisely so that the behaviour could be changed in a central way if it turned out to be necessary. > As far as I understand, this would be perfect if I had not to use a > separate thread for my terminal. Indeed, I want to send a command from > the terminal (through a menu for example) to gnuplot. I use events > defined in mouse.c, and more precisely a "command" event (which > doesn't seem to be used very often, or maybe in OS/2 only). The > do_event(event) is executed in my gui thread. When an error appears on > the command, we obtain a longjump which is invalid for *this* gui > thread... and it ends with a segmentation fault. > > I can't simply delete the longjump, as it is necessary to stop command > line parsing. If I do it, gnuplot either seems to enter in a infinite > loop or terminante with an other segfault. > Can't you just augment / replace bail_to_command_line() to make it do what you need ? Or you could save the existing jmpbuffer and do another setjmp to basically intercept the longjmp calls, letting you do any extra work, before you longjmp back to the original setjmp location. dd --=20 Dave Denholm <dde...@es...> http://www.esmertec= .com |