From: Yuriy K. <yu...@gm...> - 2014-02-12 09:24:58
|
Daniel J Sebald wrote: > On 02/09/2014 05:29 AM, Mojca Miklavec wrote: >> On Sun, Feb 9, 2014 at 12:11 PM, Mojca Miklavec wrote: >>> On Sun, Feb 9, 2014 at 1:19 AM, sfeam wrote: >>>> On Sunday, 09 February 2014 01:01:20 AM Mojca Miklavec wrote: >>>>>> Another possible test: >>>>>> Change the timeout value on line 259 from >>>>>> qt->socket.waitForConnected(200); >>>>>> to >>>>>> qt->socket.waitForConnected(-1); >>>>>> >>>>>> This could potentially cause gnuplot to hang, but it also might work >>>>> Gnuplot runs at 99% CPU with or without that change (just gnuplot, >>>>> gnuplot_qt doesn't consume any CPU at all after the first few >>>>> seconds). >>>> gnuplot is spinning CPU cycles while waiting for a timeout? >>>> The OSX implementation must really suck. >>>> Anyhow if you can see the gnuplot_qt process but the waitForConnected >>>> fails to return that's probably a huge clue to what's gone wrong. >>>> Let me think about this for a while. >>>> >>>> I'm cc-ing Jérôme Lodewyck. Maybe he can decipher the clue. >>> I don't know if that's a clue or not, but if I run gdb and manually >>> press "n", only a single gnuplot_qt is started and gnuplot actually >>> returns to the console (if I simply run gnuplot, it runs at 99% CPU >>> "forever"). The first "plot sin(x)" doesn't show anything, but when I >>> plot something for the second time, the plot is actually shown. >>> >>> So maybe there's just a problem of wrong >>> timing/synchronisation/initialisation somewhere after all. >>> >>> The fact is that if I actually get to this point (by manually stepping >>> inside gdb), it works a lot better than it did with forking: >>> - printing doesn't crash >>> - there is no need for the dirty hack removeDockIcon() >>> TransformProcessType(&psn, kProcessTransformToBackgroundApplication); >>> to hide the nofunctional window >> And indeed if I change the timeout: >> >> --- a/src/qtterminal/qt_term.cpp >> +++ b/src/qtterminal/qt_term.cpp >> @@ -251,7 +252,7 >> >> // The QLocalSocket::waitForConnected does not respect the >> time out argument when the >> // gnuplot_qt application is not yet started. To wait for it, >> we need to implement the timeout ourselves >> - QDateTime timeout = QDateTime::currentDateTime().addMSecs(1000); >> + QDateTime timeout = QDateTime::currentDateTime().addMSecs(10000); >> do >> { >> qt->socket.connectToServer(server); >> >> it suddenly almost starts working. I'm saying almost because the first >> plot doesn't work, but the second one does. >> >> Terminal type set to 'qt' >> gnuplot> plot sin(x) # nothing can be seen >> started detached process "qtgnuplot31706" >> gnuplot> plot cos(x) # works >> gnuplot> >> >> It seems that gnuplot gives up too quickly. And if it does give up, >> the second attempt to connect doesn't work properly, ends up with two >> instances of gnuplot_qt running (none of them gets closed etc). >> >> According to a gdb a lot of that "infinite cycling" (when not properly >> connected) happens with >> >> while (!receivedFontPropos) >> qt->socket.waitForReadyRead(1000); >> while (qt->socket.bytesAvailable()>= (int)sizeof(gp_event_t)) >> } >> >> The following is "sampling" of the running gnuplot at 99% CPU: > > Trying my best to decipher, but I think it's getting close now. In a > post that didn't make it here you added that you see this error: > > "Incorrect NSStringEncoding value 0x0000 detected." > > Looking at the debugger results below, it seems that qt_term.cpp is > having problems at or near lines 423-424: > >> 748,772,... [0x1001da24c,0x1001da264,...] qt_term.cpp:424 >> + 118 qt_sendFont() (in gnuplot) + >> 737,713,... [0x1001da241,0x1001da229,...] qt_term.cpp:423 >> + 110 > > and the code hunk around there is: > > while (!receivedFontPropos) > { > qt->socket.waitForReadyRead(1000); > 423 while (qt->socket.bytesAvailable() >= (int)sizeof(gp_event_t)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Not sure, but this looks very wrong. If this condition ever triggers (there are less than sizeof(...) bytes in socket), it will result in infinite busy-loop (if there are *any* bytes in socket, waitForReadyRead will instantly return, receivedFontProps is not changed, bytesAvailable check will fail again, etc). I think same apply to similar code in qt_waitforinput(). (However, it is unlikely to be related to discussed bug (I expect it can only trigger on gnuplot and gnuplot_qt version/ABI/architecture mismatch). Still, it feels a way too fragile; IMO, there should be at very least mutual validation of sizeof(gp_event_t) at startup). > 424 { > gp_event_t event; > qt->socket.read((char*) &event, sizeof(gp_event_t)); > // Here, we discard other events than fontprops. > if ((event.type == GE_fontprops) && (event.par1 > 0) && (event.par2 > > 0)) > { > receivedFontPropos = true; > metric = QPair<int, int>(event.par1, event.par2); > fontMetricCache[currentFont] = metric; > break; > } > } > } > > So, some comments: > > 1) Ethan was likely correct about the timeout. The Qt documentation > indicates the default timeout is 30 seconds. 1 second seems rather > short. Especially in this case, as font setting/info is a system > library and it is quite common for system level features to take up to > five seconds or so to complete especially the first time the are called > and loaded resident. Mojca, for a temporary measure to take this issue > out of the picture, consider setting the timeout to the default 30 > seconds (i.e., remove the argument 1000 from the function or change 1000 > to 30000). > > 2) With the error you pointed out regarding NSStringEncoding, it would > seem there might be an added delay because something isn't correct about > qt_term's requested font info string. Perhaps the system font library > can't find the metric information that is being sought and it takes a > while to prep/search the system database. > > 3) On the other hand, that error you indicated could be what happens when > > qt->socket.waitForReadyRead(1000); > while (qt->socket.bytesAvailable() >= (int)sizeof(gp_event_t)) > > fails. (Are you seeing that error when you add the really long wait > period?) > > 4) When the above does fail (i.e., times out), what happens? It looks like > > QPair<int, int> metric; > > is uninitialized, or at least defaults to a zero pair. So, if the font > info times out, what is the value of metric when used here? > > term->v_char = qt_oversampling*metric.first; > term->h_char = qt_oversampling*metric.second; > > 5) Timeout should generally be treated a little more robustly especially > given that Qt has some ready-made tools for displaying dialog boxes. > Perhaps when timeout happens, display a warning dialog about canceling > or continuing onward. Of course, that creates issues for gnuplot in > non-interactive mode. In any case, this probably isn't critical with > regard to the problems in functionality you are seeing. > > Dan > > >> Call graph: >> 2510 Thread_2393718 DispatchQueue_1: com.apple.main-thread (serial) >> + 2510 start (in gnuplot) + 52 [0x100011244] >> + 2510 main (in gnuplot) + 2796 [0x1000aa62c] plot.c:672 >> + 2510 com_line (in gnuplot) + 144 [0x100025140] command.c:323 >> + 2510 do_line (in gnuplot) + 1066 [0x10002559a] command.c:411 >> + 2510 command (in gnuplot) + 131 [0x100026283] command.c:616 >> + 2510 plot_command (in gnuplot) + 206 [0x100028d1e] >> command.c:1559 >> + 2510 plotrequest (in gnuplot) + 1763 [0x1000abf83] >> plot2d.c:273 >> + 2510 eval_plots (in gnuplot) + 27828 >> [0x1000c00c4] plot2d.c:3259 >> + 2510 do_plot (in gnuplot) + 131 [0x100062843] >> graphics.c:517 >> + 2510 term_start_plot (in gnuplot) + 63 >> [0x10011476f] term.c:557 >> + 2510 qt_graphics (in gnuplot) + 669 >> [0x1001da68d] qt_term.cpp:480 >> + 1582 qt_sendFont() (in gnuplot) + 772 >> [0x1001da264] qt_term.cpp:424 >> + ! 962 QLocalSocket::bytesAvailable() const >> (in QtNetwork) + 42 [0x1022520fa] >> + ! : 646 QAbstractSocket::bytesAvailable() >> const (in QtNetwork) + 16 [0x102245210] >> + ! : | 646 QIODevice::bytesAvailable() >> const (in QtCore) + 0,20,... [0x1030389a0,0x1030389b4,...] >> + ! : 248 QAbstractSocket::bytesAvailable() >> const (in QtNetwork) + 0,16,... [0x102245200,0x102245210,...] >> + ! : 68 >> DYLD-STUB$$QIODevice::bytesAvailable() const (in QtNetwork) + 0 >> [0x10226ca8a] >> + ! 295 QLocalSocket::bytesAvailable() const >> (in QtNetwork) + 16 [0x1022520e0] >> + ! : 295 QIODevice::bytesAvailable() const >> (in QtCore) + 0,85,... [0x1030389a0,0x1030389f5,...] >> + ! 236 QLocalSocket::bytesAvailable() const >> (in QtNetwork) + 6,16,... [0x1022520d6,0x1022520e0,...] >> + ! 89 >> DYLD-STUB$$QIODevice::bytesAvailable() const (in QtNetwork) + 0 >> [0x10226ca8a] >> + 342 qt_sendFont() (in gnuplot) + 737 >> [0x1001da241] qt_term.cpp:423 >> + ! 195 QLocalSocket::waitForReadyRead(int) >> (in QtNetwork) + 6,51,... [0x1022526c6,0x1022526f3,...] >> + ! 147 QLocalSocket::waitForReadyRead(int) >> (in QtNetwork) + 18 [0x1022526d2] >> + ! 147 QLocalSocket::state() const (in >> QtNetwork) + 0,8 [0x10224aed0,0x10224aed8] >> + 180 qt_sendFont() (in gnuplot) + >> 748,772,... [0x1001da24c,0x1001da264,...] qt_term.cpp:424 >> + 118 qt_sendFont() (in gnuplot) + >> 737,713,... [0x1001da241,0x1001da229,...] qt_term.cpp:423 >> + 110 >> DYLD-STUB$$QLocalSocket::waitForReadyRead(int) (in gnuplot) + 0 >> [0x1001e38b6] >> + 97 >> DYLD-STUB$$QLocalSocket::bytesAvailable() const (in gnuplot) + 0 >> [0x1001e38ec] >> + 47 qt_sendFont() (in gnuplot) + 695 >> [0x1001da217] qt_term.cpp:421 >> + 34 qt_sendFont() (in gnuplot) + 999 >> [0x1001da347] qt_term.cpp:437 >> 2510 Thread_2393731 DispatchQueue_2: >> com.apple.libdispatch-manager (serial) >> + 2510 _dispatch_mgr_thread (in libdispatch.dylib) + 54 [0x7fff8c328316] >> + 2510 _dispatch_mgr_invoke (in libdispatch.dylib) + 923 >> [0x7fff8c329786] >> + 2510 kevent (in libsystem_kernel.dylib) + 10 [0x7fff8b5e27e6] >> 2510 Thread_2393735: QProcessManager >> 2510 thread_start (in libsystem_c.dylib) + 13 [0x7fff89671b75] >> 2510 _pthread_start (in libsystem_c.dylib) + 335 [0x7fff8966e8bf] >> 2510 QThreadPrivate::start(void*) (in QtCore) + 504 [0x102fad238] >> 2510 QProcessManager::run() (in QtCore) + 168 [0x10307d7b8] >> 2510 __select (in libsystem_kernel.dylib) + 10 [0x7fff8b5e1df2] >> >> Total number in stack (recursive counted multiple, when>=5): >> >> Sort by top of stack, same collapsed (when>= 5): >> __select (in libsystem_kernel.dylib) 2510 >> kevent (in libsystem_kernel.dylib) 2510 >> QIODevice::bytesAvailable() const (in QtCore) 941 >> qt_sendFont() (in gnuplot) 379 >> QAbstractSocket::bytesAvailable() const (in QtNetwork) 248 >> QLocalSocket::bytesAvailable() const (in QtNetwork) 236 >> QLocalSocket::waitForReadyRead(int) (in QtNetwork) 195 >> DYLD-STUB$$QIODevice::bytesAvailable() const (in QtNetwork) 157 >> QLocalSocket::state() const (in QtNetwork) 147 >> DYLD-STUB$$QLocalSocket::waitForReadyRead(int) (in gnuplot) 110 >> DYLD-STUB$$QLocalSocket::bytesAvailable() const (in gnuplot) 97 |