[Ecls-list] threading failures

Daniel Kochmański daniel at turtleware.eu
Wed Sep 2 19:32:04 UTC 2015


James M. Lawrence writes:

> On Wed, Sep 2, 2015 at 6:09 AM, Daniel Kochmański <daniel at turtleware.eu> wrote:
>> Hm, then I can't reproduce neither of them. Spawning too many threads
>> blows the heap, but it's understandable. I think it might be that i have
>> x86_64 and a new kernel, (maybe it happens only on x86, or linux 3.2 had
>> some bug?).
>
> 64-bit systems are sometimes better at concealing such threading bugs.
> The default assumption should be that 64-bit systems just haven't been
> jiggled to the right tune yet. Over the course of several years, and
> across several kernels, I haven't seen any version of ECL pass these
> stress tests. This problem would need to be understood before even
> thinking about kernel bugs, which seem quite unlikely in this case.
>

Ok, so I guess I'll just set up 32-bit VM. I hope this will be able to
reproduce the problems (next test doesn't fail neither on my x86_64 for
my tests). Yeah, I also think that kernel bug is unlikely, but I'll keep
that possibility in mind.

I've added your tests to repository and will integrate them soon
(infinite loop isn't a good pick for regression tests :-)).

Thanks,
Daniel

> Moving up the ladder of complexity, the next test case requires a
> blocking queue and involves repeatedly creating/destroying worker
> threads. It has three different types of failures; they are sporadic
> and not determined by the inputs. The following are just example runs
> and shouldn't be considered representative:
>
> (qtest 0 64) ;=> segfault
> (qtest 1 64) ; => hang
> (qtest 10000 64) ; => error "Attempted to recursively lock..."
>
> ;;;; raw-queue
>
> (defstruct (raw-queue (:conc-name nil))
>   (head nil)
>   (tail nil))
>
> (defun push-raw-queue (value queue)
>   (let ((new (cons value nil)))
>     (if (head queue)
>         (setf (cdr (tail queue)) new)
>         (setf (head queue) new))
>     (setf (tail queue) new)))
>
> (defun pop-raw-queue (queue)
>   (let ((node (head queue)))
>     (if node
>         (multiple-value-prog1 (values (car node) t)
>           (when (null (setf (head queue) (cdr node)))
>             (setf (tail queue) nil))
>           (setf (car node) nil
>                 (cdr node) nil))
>         (values nil nil))))
>
> ;;;; queue
>
> (defstruct queue
>   (impl (make-raw-queue))
>   (lock (mp:make-lock))
>   (cvar (mp:make-condition-variable)))
>
> (defun push-queue (object queue)
>   (mp:with-lock ((queue-lock queue))
>     (push-raw-queue object (queue-impl queue))
>     (mp:condition-variable-signal (queue-cvar queue))))
>
> (defun pop-queue (queue)
>   (mp:with-lock ((queue-lock queue))
>     (loop (multiple-value-bind (value presentp)
>               (pop-raw-queue (queue-impl queue))
>             (if presentp
>                 (return value)
>                 (mp:condition-variable-wait
>                  (queue-cvar queue)
>                  (queue-lock queue)))))))
>
> ;;;; qtest
>
> (defun qtest (message-count worker-count)
>   (loop (let ((to-workers (make-queue))
>               (from-workers (make-queue)))
>           (loop repeat worker-count
>                 do (mp:process-run-function
>                     "test"
>                     (lambda ()
>                       (loop (let ((message (pop-queue to-workers)))
>                               (push-queue message from-workers)
>                               (unless message (return)))))))
>           (loop repeat message-count do (push-queue t to-workers))
>           (loop repeat message-count do (pop-queue from-workers))
>           (loop repeat worker-count do (push-queue nil to-workers))
>           (loop repeat worker-count do (pop-queue from-workers))
>           (format t ".")
>           (finish-output))))

-- 
Daniel Kochmański | Poznań, Poland
;; aka jackdaniel

"Be the change that you wish to see in the world." - Mahatma Gandhi



More information about the ecl-devel mailing list