You can subscribe to this list here.
| 2000 |
Jan
(81) |
Feb
(55) |
Mar
(459) |
Apr
(159) |
May
(126) |
Jun
(69) |
Jul
(48) |
Aug
(29) |
Sep
(106) |
Oct
(76) |
Nov
(155) |
Dec
(161) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(122) |
Feb
(150) |
Mar
(294) |
Apr
(124) |
May
(197) |
Jun
(266) |
Jul
(111) |
Aug
(259) |
Sep
(163) |
Oct
(142) |
Nov
(101) |
Dec
(86) |
| 2002 |
Jan
(187) |
Feb
(108) |
Mar
(274) |
Apr
(157) |
May
(346) |
Jun
(242) |
Jul
(345) |
Aug
(187) |
Sep
(263) |
Oct
(69) |
Nov
(30) |
Dec
(76) |
| 2003 |
Jan
(125) |
Feb
(191) |
Mar
(87) |
Apr
(69) |
May
(107) |
Jun
(66) |
Jul
(112) |
Aug
(161) |
Sep
(184) |
Oct
(137) |
Nov
(28) |
Dec
(61) |
| 2004 |
Jan
(148) |
Feb
(99) |
Mar
(365) |
Apr
(225) |
May
(311) |
Jun
(204) |
Jul
(95) |
Aug
(214) |
Sep
(256) |
Oct
(290) |
Nov
(239) |
Dec
(152) |
| 2005 |
Jan
(253) |
Feb
(183) |
Mar
(178) |
Apr
(88) |
May
(175) |
Jun
(195) |
Jul
(122) |
Aug
(81) |
Sep
(119) |
Oct
(200) |
Nov
(110) |
Dec
(179) |
| 2006 |
Jan
(154) |
Feb
(64) |
Mar
(55) |
Apr
(69) |
May
(66) |
Jun
(64) |
Jul
(80) |
Aug
(59) |
Sep
(62) |
Oct
(90) |
Nov
(132) |
Dec
(106) |
| 2007 |
Jan
(58) |
Feb
(51) |
Mar
(59) |
Apr
(19) |
May
(33) |
Jun
(52) |
Jul
(15) |
Aug
(50) |
Sep
(41) |
Oct
(259) |
Nov
(323) |
Dec
(136) |
| 2008 |
Jan
(205) |
Feb
(128) |
Mar
(203) |
Apr
(126) |
May
(307) |
Jun
(166) |
Jul
(259) |
Aug
(181) |
Sep
(217) |
Oct
(265) |
Nov
(256) |
Dec
(132) |
| 2009 |
Jan
(104) |
Feb
(81) |
Mar
(27) |
Apr
(21) |
May
(85) |
Jun
(237) |
Jul
(243) |
Aug
(199) |
Sep
(178) |
Oct
(151) |
Nov
(64) |
Dec
(39) |
| 2010 |
Jan
(33) |
Feb
(146) |
Mar
(125) |
Apr
(109) |
May
(52) |
Jun
(135) |
Jul
(103) |
Aug
(68) |
Sep
(99) |
Oct
(88) |
Nov
(45) |
Dec
(56) |
| 2011 |
Jan
(19) |
Feb
(32) |
Mar
(50) |
Apr
(105) |
May
(46) |
Jun
(22) |
Jul
(101) |
Aug
(80) |
Sep
(52) |
Oct
(16) |
Nov
(10) |
Dec
(29) |
| 2012 |
Jan
(8) |
Feb
(22) |
Mar
(17) |
Apr
(68) |
May
(19) |
Jun
(19) |
Jul
(12) |
Aug
(6) |
Sep
(13) |
Oct
(5) |
Nov
(5) |
Dec
(5) |
| 2013 |
Jan
(6) |
Feb
(4) |
Mar
(3) |
Apr
(5) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(6) |
Dec
|
| 2014 |
Jan
|
Feb
|
Mar
(16) |
Apr
(1) |
May
(8) |
Jun
|
Jul
(1) |
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2015 |
Jan
|
Feb
(8) |
Mar
(23) |
Apr
(5) |
May
|
Jun
|
Jul
|
Aug
(7) |
Sep
(1) |
Oct
|
Nov
|
Dec
(5) |
| 2016 |
Jan
|
Feb
|
Mar
(16) |
Apr
(6) |
May
(53) |
Jun
(19) |
Jul
(3) |
Aug
(39) |
Sep
(24) |
Oct
(2) |
Nov
(19) |
Dec
|
| 2017 |
Jan
(13) |
Feb
(44) |
Mar
(208) |
Apr
(12) |
May
(94) |
Jun
(54) |
Jul
(18) |
Aug
(52) |
Sep
(12) |
Oct
(22) |
Nov
(27) |
Dec
(93) |
| 2018 |
Jan
(85) |
Feb
(28) |
Mar
(16) |
Apr
(47) |
May
(16) |
Jun
(15) |
Jul
(10) |
Aug
(3) |
Sep
(5) |
Oct
|
Nov
(6) |
Dec
|
| 2019 |
Jan
(4) |
Feb
(6) |
Mar
(12) |
Apr
(1) |
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
|
| 2020 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
(6) |
Oct
|
Nov
|
Dec
|
| 2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(2) |
Dec
|
| 2022 |
Jan
(2) |
Feb
|
Mar
(5) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(10) |
Oct
(5) |
Nov
|
Dec
|
| 2023 |
Jan
|
Feb
(4) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2024 |
Jan
|
Feb
|
Mar
|
Apr
(9) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(8) |
Nov
(28) |
Dec
(3) |
| 2025 |
Jan
(8) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <don...@is...> - 2010-11-03 18:18:29
|
Sam Steingold writes: > > > (loop for x in (mt:LIST-THREADS) do > > > (format t "-- ~a --~&" x) > > > (mt:thread-interrupt x :function > > > (lambda () (let ((*debug-io* *dbg*))(ext:show-stack 1 3))))) > > > where *dbg* is the value of *debug-io* in the debugging thread. > > This still doesn't work. > > How can I use one thread to see a stack trace for another one? > > show-stack prints to *standard-output* That was my original attempt. If I change debug-io above to standard-output I get the same thing. The thread where I do the loop shows the format for all threads but the backtrace only for itself. |
|
From: <don...@is...> - 2010-11-03 18:10:36
|
Vladimir Tzankov writes:
> > A related topic that we may have discussed before:
> > There are situations where you get into an unwind-protect loop
> > and need a way to escape. So far I don't know to do this.
> > Perhaps there is some way already?
>
> I do not understand the problem - can you post an example?
I don't have a real example handy, but I'm pretty sure I've seen
(and even been stuck in) things like this
(defun f()
(prog (c)
loop
(unwind-protect
(setf c (read-char socket))
(unless c (go loop)))))
So we interrupt, find we're blocked in read-char.
Returning from read-char, of course, leaves you where you started.
If we try to return from somewhere higher up, like f, this executes
the unwind protect and we're still back where we started.
You might argue that this is what the unwind-protect is trying to do,
which is quite correct.
Basically we have a situation where the code wants to prevent the
debugger (or anything else) from doing something and the debugger (or
the user or code controlling it) wants to do that thing. Only one can
win. I think it should be the debugger. If there is no other way to
break out of an unwind-protect, that would be fine with me.
Then you could correctly reason that the loop above does not terminate
until a character has been read OR the debugger breaks out.
I think it would be reasonable to reason about programs only in the
absence of certain debugger actions.
What I suggest is a debugger command which I'll call return-break.
If I break and find myself in read-char, then return-break would
return from read-char just like the return command, but would then
break at the return site. In the case above that would be the
beginning of the first (only) cleanup form. Now we're in the
situation that was discussed a while back - we're in the debugger
in a cleanup form. At that point I can return from that form (or
more likely do another return-break), and thereby eventually escape
from the trap.
|
|
From: Sam S. <sd...@gn...> - 2010-11-03 18:07:18
|
> * Don Cohen <qba...@vf...> [2010-11-03 09:33:43 -0800]: > > > It appears that there's no stream argument. I guess now (after losing > > contact with all threads) that I should have done something like > > (loop for x in (mt:LIST-THREADS) do > > (format t "-- ~a --~&" x) > > (mt:thread-interrupt x :function > > (lambda () (let ((*debug-io* *dbg*))(ext:show-stack 1 3))))) > > where *dbg* is the value of *debug-io* in the debugging thread. > This still doesn't work. > How can I use one thread to see a stack trace for another one? show-stack prints to *standard-output* -- Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://openvotingconsortium.org http://palestinefacts.org http://www.PetitionOnline.com/tap12009/ http://honestreporting.com Bill Gates is not god and Microsoft is not heaven. |
|
From: <don...@is...> - 2010-11-03 17:33:46
|
> I do this > (loop for x in (mt:LIST-THREADS) do > (format t "-- ~a --~&" x) > (mt:thread-interrupt x :function (lambda () (ext:show-stack 1 3)))) > and I see a backtrace only for the current thread. > I see the output of the format for other threads but no backtrace. > I do see the backtrace for another thread in its listener. > It appears that there's no stream argument. I guess now (after losing > contact with all threads) that I should have done something like > (loop for x in (mt:LIST-THREADS) do > (format t "-- ~a --~&" x) > (mt:thread-interrupt x :function > (lambda () (let ((*debug-io* *dbg*))(ext:show-stack 1 3))))) > where *dbg* is the value of *debug-io* in the debugging thread. This still doesn't work. How can I use one thread to see a stack trace for another one? |
|
From: Sam S. <sd...@gn...> - 2010-11-03 16:49:39
|
> * Vladimir Tzankov <igm...@tz...> [2010-11-03 09:10:31 +0200]: > > seems there is no documentation for show-stack just added. -- Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://mideasttruth.com http://jihadwatch.org http://dhimmi.com http://www.PetitionOnline.com/tap12009/ http://honestreporting.com Those who beat their swords into plowshares plow for those who do not. |
|
From: Sam S. <sd...@gn...> - 2010-11-03 16:49:12
|
> * Don Cohen <qba...@vf...> [2010-11-02 12:02:25 -0800]: > > I notice that a > version of impnotes all in one page would be useful for searching. one is provided both on the main page and on the beta page. -- Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://memri.org http://truepeace.org http://thereligionofpeace.com http://jihadwatch.org http://honestreporting.com http://www.memritv.org Never succeed from the first try - if you do, nobody will think it was hard. |
|
From: Vladimir T. <vtz...@gm...> - 2010-11-03 07:10:38
|
On 11/2/10, Don Cohen <don...@is...> wrote: > > (thread-interrupt some-thread :function (lambda () (show-stack 1 10))) > > second argument of show-stack is number of frames to be shown. > [A little off topic, but > Is this documented? I don't see it in impnotes. I notice that a > version of impnotes all in one page would be useful for searching. > ] seems there is no documentation for show-stack > A related topic that we may have discussed before: > There are situations where you get into an unwind-protect loop > and need a way to escape. So far I don't know to do this. > Perhaps there is some way already? I do not understand the problem - can you post an example? |
|
From: <don...@is...> - 2010-11-02 20:02:34
|
Vladimir Tzankov writes: > > Otherwise (return from exemption-wait and no test or loop), it's as > > if exemption-wait returned (whatever value I chose). > Hmm, how are you going to return from exemption-wait from interrupt > function? The only way to get out of it is to perform non-local > exit. I had in mind using the debugger to do something like return or redo. I agree that these are all non-local exits. > > few functions on the stack and then resume? > (thread-interrupt some-thread :function (lambda () (show-stack 1 10))) > second argument of show-stack is number of frames to be shown. [A little off topic, but Is this documented? I don't see it in impnotes. I notice that a version of impnotes all in one page would be useful for searching. ] I do this (loop for x in (mt:LIST-THREADS) do (format t "-- ~a --~&" x) (mt:thread-interrupt x :function (lambda () (ext:show-stack 1 3)))) and I see a backtrace only for the current thread. I see the output of the format for other threads but no backtrace. I do see the backtrace for another thread in its listener. It appears that there's no stream argument. I guess now (after losing contact with all threads) that I should have done something like (loop for x in (mt:LIST-THREADS) do (format t "-- ~a --~&" x) (mt:thread-interrupt x :function (lambda () (let ((*debug-io* *dbg*))(ext:show-stack 1 3))))) where *dbg* is the value of *debug-io* in the debugging thread. A related topic that we may have discussed before: There are situations where you get into an unwind-protect loop and need a way to escape. So far I don't know to do this. Perhaps there is some way already? I'm thinking that a debugger command that does a return from the current frame and then breaks at the place where the return returns to would be useful. |
|
From: Vladimir T. <vtz...@gm...> - 2010-11-02 07:04:13
|
On 11/2/10, Don Cohen <don...@is...> wrote: > Let me try again. > Exemption-wait releases the lock and then calls pthread_cond_wait? > Or perhaps pthread_cond_wait releases the lock. pthread_cond_wait atomically releases the lock and starts to wait on condition variable (exemption in clisp). > We then try to interrupt. Which actually signals the condition in order to get out of pthread_cond_wait. > At that point pthread_cond_wait gets the lock (might have to wait for > it!) and exits but we're still in exemption-wait? So then we call > the interrupt function, e.g., debugger. And we see > - exemption-wait on the stack > - we have the lock yes > If I then do continue, the condition will be retested if :test was > supplied and that will probably go back to pthread_cond_wait. yes > If no test was supplied or if I return from exemption-wait then > if I have supplied my own loop, it will retest, call exemption-wait > again and that will call pthread_cond_wait again. that's should be the usage in case of no :test argument. > Otherwise (return from exemption-wait and no test or loop), it's as > if exemption-wait returned (whatever value I chose). Hmm, how are you going to return from exemption-wait from interrupt function? The only way to get out of it is to perform non-local exit. > > When you interrupt a thread and do not perform non-local exit from > > interrupt function - the thread resumes normally. If you inspect the > > stack from the interrupt - you will see all > > mutex-lock/exemption-wait/read/etc there. > Ok, good. What can I pass to thread-interrupt to just show the top > few functions on the stack and then resume? (thread-interrupt some-thread :function (lambda () (show-stack 1 10))) second argument of show-stack is number of frames to be shown. |
|
From: <don...@is...> - 2010-11-01 23:33:19
|
Vladimir Tzankov writes: > On 11/1/10, Don Cohen <don...@is...> wrote: > > > The only way to implement thread-interrupt while we are waiting in > > > pthread_cond_wait() is to signal the condition/exemption, run the > > > interrupt function and continue to wait. After we signal the exemption > > > - mutex is reacquired automatically by the OS. As final result - lock > > > is held when the interrupt functions is executed. > > Ok, so you can never look up the stack and find that you're in > > exemption-wait. If you interrupt while in that function you find > > yourself ready to execute the thing after it. And at that point > > exemption-wait has returned T. > > Have you tried it? exemption-wait does not return when it handles > interrupts - interrupt function is called from it. Then I misinterpreted your text above. Let me try again. Exemption-wait releases the lock and then calls pthread_cond_wait? Or perhaps pthread_cond_wait releases the lock. We then try to interrupt. At that point pthread_cond_wait gets the lock (might have to wait for it!) and exits but we're still in exemption-wait? So then we call the interrupt function, e.g., debugger. And we see - exemption-wait on the stack - we have the lock If I then do continue, the condition will be retested if :test was supplied and that will probably go back to pthread_cond_wait. If no test was supplied or if I return from exemption-wait then if I have supplied my own loop, it will retest, call exemption-wait again and that will call pthread_cond_wait again. Otherwise (return from exemption-wait and no test or loop), it's as if exemption-wait returned (whatever value I chose). Is that all correct? > When you interrupt a thread and do not perform non-local exit from > interrupt function - the thread resumes normally. If you inspect the > stack from the interrupt - you will see all > mutex-lock/exemption-wait/read/etc there. Ok, good. What can I pass to thread-interrupt to just show the top few functions on the stack and then resume? > Again - it seems you want to layer another scheduler on top of > primitives that clisp provides. Take a look at portable-threads > (http://gbbopen.org). ok, thanks |
|
From: Vladimir T. <vtz...@gm...> - 2010-11-01 18:41:36
|
On 11/1/10, Don Cohen <don...@is...> wrote: > > Let's explain why it works this way: > > Suppose you are stuck in pthread_cond_wait() and you want to interrupt > > it. According to POSIX standard this function never returns EINTR (if > > it gets signal). Rather it calls signal handler and continues to wait > > as if nothing happened. Within signal handler no lisp code can be > > executed (and actually very limited set of C functions are allowed) . > > The only way to implement thread-interrupt while we are waiting in > > pthread_cond_wait() is to signal the condition/exemption, run the > > interrupt function and continue to wait. After we signal the exemption > > - mutex is reacquired automatically by the OS. As final result - lock > > is held when the interrupt functions is executed. > Ok, so you can never look up the stack and find that you're in > exemption-wait. If you interrupt while in that function you find > yourself ready to execute the thing after it. And at that point > exemption-wait has returned T. Have you tried it? exemption-wait does not return when it handles interrupts - interrupt function is called from it. > > > > On non-local exit from the function - all unwind-protect forms will > > > > be executed and mutex in the above example will be unlocked. In > > > > case of normal exit from interrupt function - exemption-wait will > > > > continue to wait. > > > "The function" means the one running the code above? > > "interrupt function" means the function passed as :function to > > thread-interrupt to be executed in the context of the thread. > So I interrupt the thread with function NIL, which does something like > a call to cerror after the return from exemption-wait. before exemption-wait returns. > I argued that I could implement what I need to control whether a > thread is runnable by doing something in the iterrupt function that > blocks, and that this was all I needed to write my own scheduler. > Did you believe that argument? Sure - you can write your own scheduler and user thread-interrupt to suspend/resume threads (btw: portable-threads library does this - you may take a look). However, note that thread-interrupt is not very efficient (obtains a global thread lock, suspends internally the thread at safe point, sends a signal - SIGUSR1). thread-interrupt is meant mainly to be used for debugging or escaping from weird situations. Also when you call thread-interrupt you can not be sure in what state the target thread is in. > By ready to run I mean not blocked as described above. > I'd like to add another kind of blocking controlled directly by my > program, e.g. function (block thread) and (unblock thread). > So you're telling me that all this is just not supported by the OS > thread implementations. I take it that if you interrupt in a blocked > read you at least see some reading function on the stack, right? How > about mutex-lock? How about any others? When you interrupt a thread and do not perform non-local exit from interrupt function - the thread resumes normally. If you inspect the stack from the interrupt - you will see all mutex-lock/exemption-wait/read/etc there. Again - it seems you want to layer another scheduler on top of primitives that clisp provides. Take a look at portable-threads (http://gbbopen.org). |
|
From: <don...@is...> - 2010-11-01 18:12:06
|
Vladimir Tzankov writes: > On 11/1/10, Don Cohen <don...@is...> wrote: > > > If thread is interrupted while in exemption-wait the interrupt > > > function will be executed with mutex held. > > So if you interrupt the thread to go into the debugger, then all other > > threads that need to get the mutex (like to return write access) are > > stuck while you debug. And if you then interrupt another to go into > > the debugger you can't even get into the debugger cause you're stuck > > waiting for the mutex before entering the debugger. I gather you agree with all above. I think you'll admit that this is not a good thing for cases where you want most of your threads to keep working (like in a web server) while you look around in the debugger to see what's going wrong with one thread. > > It seems to me that if you interrupt exemption-wait you should not > > wait to get the lock. That's supposed to happen only before you exit > > exemption-wait and you should be able to interrupt and go into the > > debugger before that. > If you are brave enough - unlock the mutex from interrupt function - > but be careful to lock it again on exit. This actually seems reasonable - I interrupt a thread, go into the debugger, find that it's in exemption-wait and unlock the mutex. Now other threads can continue to run while I examine the state of this one. I'd like to automate the first step so that other threads do not have to wait while I figure out that I'm in exemption-wait and unlock the mutex. Where is doc that tells me how to do that? When you interrupt with function NIL to debug, is that the same as some function that I can call? I'm guessing something like (lambda nil (cerror ...)) ? Perhaps a function to show some backtrace of a given thread would be useful. > btw: debugging in presence of many threads is quite adventurous. I > find it mostly useful for fixing deadlocks - for everything else I > prefer logging. I've noticed that. It seems much more sane now that I can control which thread reads the input I type. > Let's explain why it works this way: > Suppose you are stuck in pthread_cond_wait() and you want to interrupt > it. According to POSIX standard this function never returns EINTR (if > it gets signal). Rather it calls signal handler and continues to wait > as if nothing happened. Within signal handler no lisp code can be > executed (and actually very limited set of C functions are allowed) . > The only way to implement thread-interrupt while we are waiting in > pthread_cond_wait() is to signal the condition/exemption, run the > interrupt function and continue to wait. After we signal the exemption > - mutex is reacquired automatically by the OS. As final result - lock > is held when the interrupt functions is executed. Ok, so you can never look up the stack and find that you're in exemption-wait. If you interrupt while in that function you find yourself ready to execute the thing after it. And at that point exemption-wait has returned T. So it's not so easy to even see that the thread you're considering debugging is in exemption-wait ! There really ought to be a way to find out what threads are waiting and for what. > > > On non-local exit from the function - all unwind-protect forms will > > > be executed and mutex in the above example will be unlocked. In > > > case of normal exit from interrupt function - exemption-wait will > > > continue to wait. > > "The function" means the one running the code above? > "interrupt function" means the function passed as :function to > thread-interrupt to be executed in the context of the thread. So I interrupt the thread with function NIL, which does something like a call to cerror after the return from exemption-wait. I then try to return from something outside the exemption-wait loop and get stuck back in it. The typical fight between debugger and unwind protect. Whereas, if I did not use the :test argument to exemption-wait, but wrote my own loop, I could return from that loop and escape the wait. Sounds like a reason to write my own loop. I suppose all of this also applies to the case of interrupt with function T to terminate the thread? > > > With native OS preemptive threads - we do not have control on the > > > scheduler. We may influence it with mutex and exemptions. > > This seems strange. Wouldn't one normally wish to control which > > threads run when more are ready to run than there are processors > > available to run them? I'm not blaming you, of course! > > (Unless you have a lot more to do with the design than I imagine.) > Not sure I understand. You control threads being executed via mutexes > and exemptions - that's all. I argued that I could implement what I need to control whether a thread is runnable by doing something in the iterrupt function that blocks, and that this was all I needed to write my own scheduler. Did you believe that argument? > > > > BTW, it seems to me that there should also be some some way to > > > > control which of several threads waiting to run should be > > > > scheduled next. Why is that either not possible or a bad idea? > > > Use distinct exemptions for this (and share the mutex if needed). > > Just off hand I don't see how this solves the problem. > > Suppose each thread had a priority (integer) - how would you arrange > > to always resume a thread of highest priority among those ready to > > run? > What do you mean by "thread ready to run"? All threads are running all > the time until they exit - just some of them are blocked in calls like > mutex-lock, exemption-wait, read(), etc and do not consume cpu cycles. > Only OS kernel knows when a thread is in such blocked state and why. By ready to run I mean not blocked as described above. I'd like to add another kind of blocking controlled directly by my program, e.g. function (block thread) and (unblock thread). So you're telling me that all this is just not supported by the OS thread implementations. I take it that if you interrupt in a blocked read you at least see some reading function on the stack, right? How about mutex-lock? How about any others? > Looks like you want to process some prioritized tasks. If so - I would > do something like: > 1. define a job > 2. maintain sorted by priority collection of jobs. guard with mutex > and signal an exemption when new highest priority item arrives. > 3. create (pool of) thread(s) - for jobs execution. wait with > exemption on the collection of jobs and execute when available (when > collection is not empty). > 4. In case all threads are busy executing jobs and new highest > priority job arrives and you are absolutely sure you want to execute > it immediately - spawn a new thread or implement kind of job > cancellation in order to release thread from the pool. This is not as good as my proposed scheduler. In particular, when a running job is no longer as worthy as some other job waiting to run I'd like to suspend its thread -- so it can be later resumed when it is again worth running. I also want to be able to notify the scheduler (a thread) when some operation blocks or unblocks so that it can block or unblock others in compensation. It would also be good for the scheduler to be able to read the run time of each thread so that it can tell, e.g., that lisp is now using 2 of the four cpus so we should try to block all but the two most urgent threads. I view this as an inadequacy of the OS thread implementations. I'm guessing that some thread implementations support the sort of thing I'm describing and some don't, so it's probably only an inadequacy of some of them. |
|
From: Vladimir T. <vtz...@gm...> - 2010-11-01 10:56:59
|
On 11/1/10, Don Cohen <don...@is...> wrote: > > If thread is interrupted while in exemption-wait the interrupt > > function will be executed with mutex held. > So if you interrupt the thread to go into the debugger, then all other > threads that need to get the mutex (like to return write access) are > stuck while you debug. And if you then interrupt another to go into > the debugger you can't even get into the debugger cause you're stuck > waiting for the mutex before entering the debugger. > It seems to me that if you interrupt exemption-wait you should not > wait to get the lock. That's supposed to happen only before you exit > exemption-wait and you should be able to interrupt and go into the > debugger before that. If you are brave enough - unlock the mutex from interrupt function - but be careful to lock it again on exit. btw: debugging in presence of many threads is quite adventurous. I find it mostly useful for fixing deadlocks - for everything else I prefer logging. Let's explain why it works this way: Suppose you are stuck in pthread_cond_wait() and you want to interrupt it. According to POSIX standard this function never returns EINTR (if it gets signal). Rather it calls signal handler and continues to wait as if nothing happened. Within signal handler no lisp code can be executed (and actually very limited set of C functions are allowed) . The only way to implement thread-interrupt while we are waiting in pthread_cond_wait() is to signal the condition/exemption, run the interrupt function and continue to wait. After we signal the exemption - mutex is reacquired automatically by the OS. As final result - lock is held when the interrupt functions is executed. > > On non-local exit from the function - all unwind-protect forms will > > be executed and mutex in the above example will be unlocked. In > > case of normal exit from interrupt function - exemption-wait will > > continue to wait. > "The function" means the one running the code above? "interrupt function" means the function passed as :function to thread-interrupt to be executed in the context of the thread. > > With native OS preemptive threads - we do not have control on the > > scheduler. We may influence it with mutex and exemptions. > This seems strange. Wouldn't one normally wish to control which > threads run when more are ready to run than there are processors > available to run them? I'm not blaming you, of course! > (Unless you have a lot more to do with the design than I imagine.) Not sure I understand. You control threads being executed via mutexes and exemptions - that's all. > > > BTW, it seems to me that there should also be some some way to control > > > which of several threads waiting to run should be scheduled next. Why > > > is that either not possible or a bad idea? > > Use distinct exemptions for this (and share the mutex if needed). > Just off hand I don't see how this solves the problem. > Suppose each thread had a priority (integer) - how would you arrange > to always resume a thread of highest priority among those ready to > run? What do you mean by "thread ready to run"? All threads are running all the time until they exit - just some of them are blocked in calls like mutex-lock, exemption-wait, read(), etc and do not consume cpu cycles. Only OS kernel knows when a thread is in such blocked state and why. Looks like you want to process some prioritized tasks. If so - I would do something like: 1. define a job 2. maintain sorted by priority collection of jobs. guard with mutex and signal an exemption when new highest priority item arrives. 3. create (pool of) thread(s) - for jobs execution. wait with exemption on the collection of jobs and execute when available (when collection is not empty). 4. In case all threads are busy executing jobs and new highest priority job arrives and you are absolutely sure you want to execute it immediately - spawn a new thread or implement kind of job cancellation in order to release thread from the pool. |
|
From: <don...@is...> - 2010-11-01 08:11:20
|
Vladimir Tzankov writes: > > So you're supposed to do something like this, right? > > (with-mutext-lock m > > (if (exemption-wait e m (lambda () <condition>)) > > ;; condition should be something that can only become true/false > > ;; due to something executed by a thread owning mutex m, right? > yes > > ;; that's why we expect that evaluating the condition while > > ;; holding m will not be affected by race conditions > > (;; now I have the lock and condition is true > > ...) > > (;; exemption-wait returns false > > ;; I have the lock but condition is (probably still) false > > ;; This can happen only if I supply a timeout? > only on timeout (or on some obscure error but if happens - it is error > in clisp implementation). > > ;; Or can it occur if this thread is interrupted? > > ...)) > > ) > > If thread is interrupted while in exemption-wait the interrupt > function will be executed with mutex held. So if you interrupt the thread to go into the debugger, then all other threads that need to get the mutex (like to return write access) are stuck while you debug. And if you then interrupt another to go into the debugger you can't even get into the debugger cause you're stuck waiting for the mutex before entering the debugger. It seems to me that if you interrupt exemption-wait you should not wait to get the lock. That's supposed to happen only before you exit exemption-wait and you should be able to interrupt and go into the debugger before that. > On non-local exit from the function - all unwind-protect forms will > be executed and mutex in the above example will be unlocked. In > case of normal exit from interrupt function - exemption-wait will > continue to wait. "The function" means the one running the code above? I would expect that if you interrupt in exemption-wait then if you return from the function, there would be an unwind protect that gets the lock to exit from exemption-wait, but then it's not so clear what should happen. I gather that if the unwind-protect returns you to a loop then there may be no way to get out of that loop. And this is not a good thing in my mind. I think the debugger should be able to get you out. But in any case, you should be able to use the debugger to return nil from exemption-wait. Even if no timeout was supplied. If you return T then I agree that the loop would be reexecuted (if condition were supplied). > > Now that I think I understand what exemptions are supposed to mean, > > it occurs to me that they could be implemented in lisp if we only had > > the ability to make a thread schedulable or not.(*) > With native OS preemptive threads - we do not have control on the > scheduler. We may influence it with mutex and exemptions. This seems strange. Wouldn't one normally wish to control which threads run when more are ready to run than there are processors available to run them? I'm not blaming you, of course! (Unless you have a lot more to do with the design than I imagine.) > > BTW, it seems to me that there should also be some some way to control > > which of several threads waiting to run should be scheduled next. Why > > is that either not possible or a bad idea? > Use distinct exemptions for this (and share the mutex if needed). Just off hand I don't see how this solves the problem. Suppose each thread had a priority (integer) - how would you arrange to always resume a thread of highest priority among those ready to run? There must already be a notion of a thread being ready to run, right? Can that be read? Can you read whether a thread is running? |
|
From: Vladimir T. <vtz...@gm...> - 2010-11-01 07:24:59
|
On 11/1/10, Don Cohen <don...@is...> wrote: > I'm only gradually beginning to understand what exemptions > are supposed to do. If my interpretation below is correct then > perhaps some of it should be added to the doc. > > Looking at doc for exemption-wait > On return mutex is acquired again. > This is true even on timeout? Yes, in all cases. When the control returns from exemption-wait - the mutex is owned by the thread regardless what caused exemption-wait to return. > So you're supposed to do something like this, right? > (with-mutext-lock m > (if (exemption-wait e m (lambda () <condition>)) > ;; condition should be something that can only become true/false > ;; due to something executed by a thread owning mutex m, right? yes > ;; that's why we expect that evaluating the condition while > ;; holding m will not be affected by race conditions > (;; now I have the lock and condition is true > ...) > (;; exemption-wait returns false > ;; I have the lock but condition is (probably still) false > ;; This can happen only if I supply a timeout? only on timeout (or on some obscure error but if happens - it is error in clisp implementation). > ;; Or can it occur if this thread is interrupted? > ...)) > ) If thread is interrupted while in exemption-wait the interrupt function will be executed with mutex held. On non-local exit from the function - all unwind-protect forms will be executed and mutex in the above example will be unlocked. In case of normal exit from interrupt function - exemption-wait will continue to wait. > Now that I think I understand what exemptions are supposed to mean, > it occurs to me that they could be implemented in lisp if we only had > the ability to make a thread schedulable or not.(*) With native OS preemptive threads - we do not have control on the scheduler. We may influence it with mutex and exemptions. > An exemption seems to be mainly a queue of threads waiting for > something. While they are waiting they are not schedulable, i.e., > they should not run. Exemption signal and broadcast then simply make > either the first or all on the queue schedulable (and remove them > from the queue). > At the moment I don't see where spurious wakeups would come from. I've observed spurious wakeups when signals are delivered to the process. > BTW, it seems to me that there should also be some some way to control > which of several threads waiting to run should be scheduled next. Why > is that either not possible or a bad idea? Use distinct exemptions for this (and share the mutex if needed). |
|
From: <don...@is...> - 2010-11-01 03:57:25
|
I'm only gradually beginning to understand what exemptions
are supposed to do. If my interpretation below is correct then
perhaps some of it should be added to the doc.
Looking at doc for exemption-wait
On return mutex is acquired again.
This is true even on timeout?
So you're supposed to do something like this, right?
(with-mutext-lock m
(if (exemption-wait e m (lambda () <condition>))
;; condition should be something that can only become true/false
;; due to something executed by a thread owning mutex m, right?
;; that's why we expect that evaluating the condition while
;; holding m will not be affected by race conditions
(;; now I have the lock and condition is true
...)
(;; exemption-wait returns false
;; I have the lock but condition is (probably still) false
;; This can happen only if I supply a timeout?
;; Or can it occur if this thread is interrupted?
...))
)
If exemption wait returned false and this does not re-acquire the lock
then I presume that the with-mutex-lock does not unlock m since
unlocking m when it's not locked is supposed to be an error.
Now that I think I understand what exemptions are supposed to mean,
it occurs to me that they could be implemented in lisp if we only had
the ability to make a thread schedulable or not.(*)
An exemption seems to be mainly a queue of threads waiting for
something. While they are waiting they are not schedulable, i.e.,
they should not run. Exemption signal and broadcast then simply make
either the first or all on the queue schedulable (and remove them
from the queue).
At the moment I don't see where spurious wakeups would come from.
(*) It occurs to me that this could actually be implemented by using
things like blocking read from a stream for wait and write to the
stream as signal, but it feels like some more direct implementation
ought to be easier.
BTW, it seems to me that there should also be some some way to control
which of several threads waiting to run should be scheduled next. Why
is that either not possible or a bad idea?
|
|
From: Sam S. <sd...@gn...> - 2010-11-01 03:35:52
|
> * Vladimir Tzankov <igm...@tz...> [2010-10-31 16:51:29 +0200]: > > On 10/31/10, Don Cohen <don...@is...> wrote: >> BTW, I'm guessing that gensym and gentemp are not protected in any way, >> so that two different threads could end up using the same names, >> and in the case of gentemp, returning the same symbols? > > gensym is not guarded in any way and it's possible to get same name in > different treads (by default every thread binds *gensym-counter* via > *default-special-bindings*). In presence of possible conflicts - may > be use unique thread prefix? > > gentemp is more problematic (have not looked on it till now). Again - > per thread prefix usage is fine but the internal counter is shared > among all threads. > > Another option is to use a form of atomic increment of counters (but > how exactly to do is problematic - cpu supported atomic increment does > not fit well clisp arithmetic, may be use mutex?). I think using a mutex in getsym & gentems (and not binding *gensym-counter* in every thread) is a good idea. these functions are usually called in macroexpansion, so they are not too speed-critical and not particularly prone to deadlocks. -- Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://thereligionofpeace.com http://www.memritv.org http://pmw.org.il http://camera.org http://mideasttruth.com http://palestinefacts.org I'm out of my mind, but feel free to leave a message... |
|
From: <don...@is...> - 2010-10-31 15:53:32
|
Vladimir Tzankov writes: > gensym is not guarded in any way and it's possible to get same name in > different treads (by default every thread binds *gensym-counter* via > *default-special-bindings*). In presence of possible conflicts - may What's the advantage of binding it per thread? This seems even worse than sharing it. It seems in that case you're actually making it very likely to use the same names in different contexts. > be use unique thread prefix? This doesn't seem all that useful since it's common (at least for me) to pass a string argument to gensym. It seems to me that the ideal behavior would be to make it work as if protected by a mutex. > gentemp is more problematic (have not looked on it till now). Again - > per thread prefix usage is fine but the internal counter is shared > among all threads. This seems similar, only even more important to return different results. That is, after all, what the spec says. |
|
From: Vladimir T. <vtz...@gm...> - 2010-10-31 14:51:37
|
On 10/31/10, Don Cohen <don...@is...> wrote: > BTW, I'm guessing that gensym and gentemp are not protected in any way, > so that two different threads could end up using the same names, > and in the case of gentemp, returning the same symbols? gensym is not guarded in any way and it's possible to get same name in different treads (by default every thread binds *gensym-counter* via *default-special-bindings*). In presence of possible conflicts - may be use unique thread prefix? gentemp is more problematic (have not looked on it till now). Again - per thread prefix usage is fine but the internal counter is shared among all threads. Another option is to use a form of atomic increment of counters (but how exactly to do is problematic - cpu supported atomic increment does not fit well clisp arithmetic, may be use mutex?). How other lisps deal with this? |
|
From: <don...@is...> - 2010-10-31 06:31:41
|
Sam Steingold writes: > > However I am not sure where in impnotes to describe per thread > > get-internal-run-time and system::%%time changes. Should this go under > > mt section (the optional argument is accepted and ignored in single > > thread builds)? I suggest mentioning it in 25.4 where you'd expect to find notes about get-internal-run-time, and also in 32.5, though I don't know where. I wonder why packages, clos, etc. are under general principles. BTW, I'm guessing that gensym and gentemp are not protected in any way, so that two different threads could end up using the same names, and in the case of gentemp, returning the same symbols? |
|
From: Sam S. <sd...@gn...> - 2010-10-31 06:02:09
|
> * Vladimir Tzankov <igm...@tz...> [2010-10-31 00:12:10 +0300]: > > On 10/29/10, Sam Steingold <sd...@gn...> wrote: >>> If you agree - I'll implement it (and document it together with per >>> thread timing) these days. >> thanks! > > I added optional :test predicate to exemption-wait and have documented > it. thanks! > However I am not sure where in impnotes to describe per thread > get-internal-run-time and system::%%time changes. Should this go under > mt section (the optional argument is accepted and ignored in single > thread builds)? no, I think you should add a note about this to impbody.xml, where the symbols are documented. -- Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://openvotingconsortium.org http://dhimmi.com http://truepeace.org http://thereligionofpeace.com http://pmw.org.il http://palestinefacts.org Fighting for peace is like screwing for virginity. |
|
From: Vladimir T. <vtz...@gm...> - 2010-10-30 21:12:17
|
On 10/29/10, Sam Steingold <sd...@gn...> wrote: >> If you agree - I'll implement it (and document it together with per >> thread timing) these days. > thanks! I added optional :test predicate to exemption-wait and have documented it. However I am not sure where in impnotes to describe per thread get-internal-run-time and system::%%time changes. Should this go under mt section (the optional argument is accepted and ignored in single thread builds)? |
|
From: SourceForge.net <no...@so...> - 2010-10-29 01:07:43
|
Bugs item #3097011, was opened at 2010-10-27 21:55 Message generated for change (Comment added) made by sds You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3097011&group_id=1355 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: clisp Group: ANSI compliance issue Status: Closed Resolution: Invalid Priority: 5 Private: No Submitted By: Wayne Iba () Assigned to: Sam Steingold (sds) Summary: read over socket confuses CR/LF Initial Comment: When reading over a socket, clisp reads a carriage-return/line-feed character _pair_ as a #\Newline character (single). After returning the #\Newline, (listen mysock) still reports T even when there is nothing left to return. This does not happen if reading from a string directly. ;;set up (setq foo (concatenate 'string "any thing here" (string (code-char 13)) (string (code-char 10)))) ;; then, (with-input-from-string (is gak) (loop while (listen is) collect (read-char is))) ;; reports correctly, but if you send gak over a socket and read from the socket, it will read a #\Newline (skipping over the #\Return) but (listen sock) will report T ;; with the result that any read hangs waiting for input which is not there although listen indicated there was something. ---------------------------------------------------------------------- >Comment By: Sam Steingold (sds) Date: 2010-10-28 21:07 Message: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=504514 https://bugs.launchpad.net/ubuntu/+source/clisp/+bug/603313 ---------------------------------------------------------------------- Comment By: Wayne Iba () Date: 2010-10-28 17:38 Message: Thanks! It works for me with 2.49. Any idea why Ubuntu bundles such an old release in 10.04? ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 15:16 Message: your code works just fine for me with the current clisp. it is quite possible that the bug you are reporting have been fixed since 2.44 was released a few years ago. please upgrade to clisp 2.49. ---------------------------------------------------------------------- Comment By: Wayne Iba () Date: 2010-10-28 14:21 Message: Yes, it seems the problem is that CLISP reads the CRLF pair as #\Newline, but somehow listen doesn't get the message and reports that there is more to be read. But attempting to read then hangs because both the #\Return and #\Linefeed have been consumed. At least, that's my theory. To replicate (w/ GNU CLISP 2.44.1 Ubuntu 10.04) [23]> (setf gak (concatenate 'string "four" (string #\Return) (string #\Linefeed))) "four " [25]> (with-input-from-string (is gak) (loop while (listen is) collect (read-char is))) (#\f #\o #\u #\r #\Return #\Newline) [26]> So things are OK so far, at least with reading from the string. Create socket to another CLISP process. Send the string, gak, to the client. [28]> (format sockstream* "~A" gak) NIL [29]> On the client, attempting the similar read hangs: [5]> (loop while (listen sockstream*) collect (read-char sockstream*)) ^C *** - Ctrl-C: User break The following restarts are available: ABORT :R1 Abort main loop Break 1 [6]> And if we try again with a more cautious reading gives the following but (listen sockstream) still reports T but hangs when read-char [14]> (loop for i below 5 collect (read-char sockstream*)) (#\f #\o #\u #\r #\Newline) [15]> (listen sockstream*) T [16]> (read-char sockstream*) ^C *** - Ctrl-C: User break The following restarts are available: ABORT :R1 Abort main loop Break 1 [17]> Using SBCL as the client (but still CLISP as the server), I can drain the socket getting the list (#\f #\o #\u #\r #\Return #\Newline) I apologize if this is not a CLISP problem, but instead a problem with my sockets implementation. I'm using CLOCC (with both CLISP and SBCL). ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 12:25 Message: 1. reading from a socket CRLF --> #\Newline: http://clisp.sourceforge.net/impnotes/clhs-newline.html 2. listen returning T and read-char hanging: cannot reproduce, please give detailed instructions. when one clisp writes foo to a socket, the other reads (#\a #\n #\y #\Space #\t #\h #\i #\n #\g #\Space #\h #\e #\r #\e #\Newline) from it, as expected. ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 12:25 Message: This bug report is now marked as "pending"/"invalid". This means that we think that the problem you report is not a problem with CLISP. Unless you - the reporter - act within 2 weeks, the bug will be permanently closed. Sorry about the inconvenience - we hope your silence means that you agree that this is not a bug in CLISP. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3097011&group_id=1355 |
|
From: SourceForge.net <no...@so...> - 2010-10-28 23:20:07
|
Bugs item #3086793, was opened at 2010-10-13 17:25 Message generated for change (Comment added) made by sf-robot You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3086793&group_id=1355 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: clisp Group: ANSI compliance issue >Status: Closed Resolution: Works For Me Priority: 5 Private: No Submitted By: Steven Harris (seh) Assigned to: Sam Steingold (sds) Summary: double-float-epsilon (and negative) invariants don't hold Initial Comment: This problem looks similar to bug 501969, closed back in 2002. CLISP violates the contracts specified in the Hyperspec for double-float-epsilon and double-float-negative-epsilon, though it does work fine for single-float-epsilon and single-float-negative-epsilon. http://www.lispworks.com/documentation/HyperSpec/Body/v_short_.htm CL-USER> (not (= (float 1 double-float-epsilon) (+ (float 1.0d0 double-float-epsilon) double-float-epsilon))) NIL CL-USER> (not (= (float 1 double-float-negative-epsilon) (- (float 1 double-float-negative-epsilon) double-float-negative-epsilon))) NIL I'm using the CLISP binary supplied by the Cygwin project on Windows XP. % uname -a CYGWIN_NT-5.1 PA10-5ZYH3M1 1.7.7(0.230/5/3) 2010-08-31 09:58 i686 Cygwin % clisp --version GNU CLISP 2.48 (2009-07-28) (built on ATGRZWN502840.avl01.avlcorp.lan [157.247.26.41]) Software: GNU C 4.3.4 20090804 (release) 1 gcc-4 -O2 -pipe -g -W -Wswitch -Wcomment -Wpointer-arith -Wimplicit -Wreturn-type -Wmissing-declarations -Wno-sign-compare -Wno-format-nonliteral -O2 -fexpensive-optimizations -falign-functions=4 -DUNICODE -DDYNAMIC_FFI -I. -Wl,--stack,8388608 -Wl,--enable-auto-import /usr/lib/libintl.dll.a /usr/lib/libiconv.dll.a /usr/lib/libreadline.dll.a -lncurses /usr/lib/libavcall.a /usr/lib/libcallback.a /usr/lib/libiconv.dll.a -L/usr/lib -lsigsegv SAFETY=0 HEAPCODES STANDARD_HEAPCODES SPVW_PAGES SPVW_MIXED libsigsegv 2.8 libiconv 1.13 libreadline 6.0 Features: (READLINE REGEXP SYSCALLS I18N LOOP COMPILER CLOS MOP CLISP ANSI-CL COMMON-LISP LISP=CL INTERPRETER SOCKETS GENERIC-STREAMS LOGICAL-PATHNAMES SCREEN FFI GETTEXT UNICODE BASE-CHAR=CHARACTER PC386 UNIX CYGWIN) C Modules: (clisp i18n syscalls regexp readline) Installation directory: /usr/lib/clisp-2.48/ User language: ENGLISH Machine: I686 (I686) PA10-5ZYH3M1.gddsi.com [10.245.57.23] ---------------------------------------------------------------------- >Comment By: SourceForge Robot (sf-robot) Date: 2010-10-28 23:20 Message: This Tracker item was closed automatically by the system. It was previously set to a Pending status, and the original submitter did not respond within 14 days (the time period specified by the administrator of this Tracker). ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-14 22:33 Message: This bug report is now marked as "pending"/"works for me". This means that we think that we cannot reproduce the problem and cannot do anything about it. Unless you - the reporter - act within 2 weeks (e.g., by submitting a self-contained test case or answering our other recent requests), the bug will be permanently closed. Sorry about the inconvenience - we hope your silence means that you are no longer observing the problem either. ---------------------------------------------------------------------- Comment By: Steven Harris (seh) Date: 2010-10-13 23:27 Message: Thank you, Sam. I'll have to wait for a few days before I can post to the Cygwin mailing list, but I'll inquire there next. By the way, I had tried to post a comment relating this problem to a similar discussion on the CMUCL mailing list from August 2003. Perhaps my comment was not saved properly. Here are the references again: http://osdir.com/ml/lisp.cmucl.devel/2003-08/msg00226.html http://osdir.com/ml/lisp.cmucl.devel/2003-08/threads.html ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-13 17:44 Message: I cannot reproduce the problem either on linux or mingw or cygwin (CYGWIN_NT-5.2 ... 1.5.25(0.156/4/2) 2008-06-12 19:34 i686 Cygwin) either with cvs head or 2.48. the forms above return T. actually, this is tested by the regression test suite , so the cygwin clisp maintainer should have noticed the problem before he distributed the package. the only difference I see between your setup and mine is that you have cyginw 1.7 on winXP and I have cygwin 1.5 on server 2003. I think it would be a good idea to ask the clisp cygwin maintainer about this (ask on the cygwin mailing list). ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3086793&group_id=1355 |
|
From: SourceForge.net <no...@so...> - 2010-10-28 21:38:58
|
Bugs item #3097011, was opened at 2010-10-28 01:55 Message generated for change (Comment added) made by You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3097011&group_id=1355 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: clisp Group: ANSI compliance issue >Status: Closed Resolution: Invalid Priority: 5 Private: No Submitted By: Wayne Iba () Assigned to: Sam Steingold (sds) Summary: read over socket confuses CR/LF Initial Comment: When reading over a socket, clisp reads a carriage-return/line-feed character _pair_ as a #\Newline character (single). After returning the #\Newline, (listen mysock) still reports T even when there is nothing left to return. This does not happen if reading from a string directly. ;;set up (setq foo (concatenate 'string "any thing here" (string (code-char 13)) (string (code-char 10)))) ;; then, (with-input-from-string (is gak) (loop while (listen is) collect (read-char is))) ;; reports correctly, but if you send gak over a socket and read from the socket, it will read a #\Newline (skipping over the #\Return) but (listen sock) will report T ;; with the result that any read hangs waiting for input which is not there although listen indicated there was something. ---------------------------------------------------------------------- >Comment By: Wayne Iba () Date: 2010-10-28 21:38 Message: Thanks! It works for me with 2.49. Any idea why Ubuntu bundles such an old release in 10.04? ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 19:16 Message: your code works just fine for me with the current clisp. it is quite possible that the bug you are reporting have been fixed since 2.44 was released a few years ago. please upgrade to clisp 2.49. ---------------------------------------------------------------------- Comment By: Wayne Iba () Date: 2010-10-28 18:21 Message: Yes, it seems the problem is that CLISP reads the CRLF pair as #\Newline, but somehow listen doesn't get the message and reports that there is more to be read. But attempting to read then hangs because both the #\Return and #\Linefeed have been consumed. At least, that's my theory. To replicate (w/ GNU CLISP 2.44.1 Ubuntu 10.04) [23]> (setf gak (concatenate 'string "four" (string #\Return) (string #\Linefeed))) "four " [25]> (with-input-from-string (is gak) (loop while (listen is) collect (read-char is))) (#\f #\o #\u #\r #\Return #\Newline) [26]> So things are OK so far, at least with reading from the string. Create socket to another CLISP process. Send the string, gak, to the client. [28]> (format sockstream* "~A" gak) NIL [29]> On the client, attempting the similar read hangs: [5]> (loop while (listen sockstream*) collect (read-char sockstream*)) ^C *** - Ctrl-C: User break The following restarts are available: ABORT :R1 Abort main loop Break 1 [6]> And if we try again with a more cautious reading gives the following but (listen sockstream) still reports T but hangs when read-char [14]> (loop for i below 5 collect (read-char sockstream*)) (#\f #\o #\u #\r #\Newline) [15]> (listen sockstream*) T [16]> (read-char sockstream*) ^C *** - Ctrl-C: User break The following restarts are available: ABORT :R1 Abort main loop Break 1 [17]> Using SBCL as the client (but still CLISP as the server), I can drain the socket getting the list (#\f #\o #\u #\r #\Return #\Newline) I apologize if this is not a CLISP problem, but instead a problem with my sockets implementation. I'm using CLOCC (with both CLISP and SBCL). ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 16:25 Message: 1. reading from a socket CRLF --> #\Newline: http://clisp.sourceforge.net/impnotes/clhs-newline.html 2. listen returning T and read-char hanging: cannot reproduce, please give detailed instructions. when one clisp writes foo to a socket, the other reads (#\a #\n #\y #\Space #\t #\h #\i #\n #\g #\Space #\h #\e #\r #\e #\Newline) from it, as expected. ---------------------------------------------------------------------- Comment By: Sam Steingold (sds) Date: 2010-10-28 16:25 Message: This bug report is now marked as "pending"/"invalid". This means that we think that the problem you report is not a problem with CLISP. Unless you - the reporter - act within 2 weeks, the bug will be permanently closed. Sorry about the inconvenience - we hope your silence means that you agree that this is not a bug in CLISP. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=101355&aid=3097011&group_id=1355 |