[M3devel] Ho hum... AtFork...

mika at async.caltech.edu mika at async.caltech.edu
Wed Aug 13 06:54:15 CEST 2014


Yeah OK 1.262 makes a lot more sense to me but I'm still not getting
things to work and now I'm really baffled because I think I understand
this code!

What I did was I threw away all my changes and reverted ThreadPThread.m3
to 1.262 as you suggested.

Rebuilt the compiler with upgrade.sh

Then rebuilt the compiler again with itself.

Then I realcleaned the world and buildshipped it.  (I was afraid
that parseparams, also imported by the thread tester, would pollute
it somehow.)

When I look at the code in 1.262 it looks quite straightforward.  heapMu
is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes.  Condition
variables are mutexes too, but that's no big deal.

So, rebuild thread tester, run it:

new source -> compiling Main.m3
 -> linking threadtest
root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # AMD64_FREEBSD/threadtest 
Writing file...done
Creating read threads...done
Creating fork threads...done
Creating alloc threads...done
Creating lock threads...done
running...printing oldest/median age/newest
.

***
*** runtime error:
***    Segmentation violation - possible attempt to dereference NIL.........laziest thread is 1407901189/1407901189/9 (tests: read 1407901189/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc 9/9/9 lock 1407901189/1407901189/9)




^C
root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$
gdb AMD64_FREEBSD/threadtest
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "amd64-marcel-freebsd"...
(gdb) run
Starting program: /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/threadtest 
[New LWP 100121]
Writing file...done
Creating read threads...done
Creating fork threads...done
Creating alloc threads...done
Creating lock threads...done
running...printing oldest/median age/newest
.[New Thread 801807000 (LWP 100343/threadtest)]
[New Thread 801807c00 (LWP 100667/threadtest)]
[New Thread 801808800 (LWP 100816/threadtest)]
[New Thread 801807400 (LWP 100349/threadtest)]
[New Thread 801808400 (LWP 100815/threadtest)]
[New Thread 801807800 (LWP 100352/threadtest)]
[New Thread 801808c00 (LWP 100817/threadtest)]
[New Thread 801809000 (LWP 100818/threadtest)]
[New Thread 801809800 (LWP 100820/threadtest)]
[New Thread 801808000 (LWP 100678/threadtest)]
[New Thread 801806400 (LWP 100121/threadtest)]
[New Thread 801806800 (LWP 100341/threadtest)]
[New Thread 801806c00 (LWP 100342/threadtest)]
.ERROR: pthread_mutex_lock:11

Program received signal SIGABRT, Aborted.
[Switching to Thread 801809800 (LWP 100820/threadtest)]
0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
(gdb) where
#0  0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
#1  0x0000000800e23ac9 in abort () from /lib/libc.so.7
#2  0x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000fe5f2d98: Bad address.
) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
#3  0x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000fe5f2dc8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:119
#4  0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000fe5f2df8: Bad address.
) at ../src/Main.m3:319
#5  0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000fe5f2eb8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:449
#6  0x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000fe5f2f68: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:422
#7  0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3
#8  0x0000000000000000 in ?? ()
(gdb) set lang c
(gdb) thread apply all bt
... not that interesting ...

Segfault is segfault---error 11 is EDEADLK (locking against myself?)

????? the code is very straightforward, as I said.  

I thought people had the thread tester working with pthreads?  Which set of files, then?  Anyone on FreeBSD/amd64?

Could it be an issue with "volatile"?  Not even sure where to look.

The code calling the lock is just this:

PROCEDURE GetChar (rd: T): CHAR
  RAISES {EndOfFile, Failure, Alerted} =
  BEGIN
    LOCK rd DO
      RETURN FastGetChar(rd);
    END
  END GetChar;

No mysteries there...

Ah is this the fork bug?  Looks like the Init routine is called on a
lot of NIL mutexes around the fork.  But the subprocesses aren't meant
to accesses the mutexes... humm

Hmm, and it's not entirely a fork issue.  Even with "threadtest -tests STD,-fork,-forktoomuch" it misbehaves.  Hangs....

Looks like a deadlock this time.

Some stacks...

Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
#0  0x00000000004b4e2b in __vdso_gettimeofday ()
#1  0x00000000004ab8d2 in gettimeofday ()
#2  0x0000000000452e4b in TimePosix__Now () at ../src/time/POSIX/TimePosixC.c:50
#3  0x0000000000452d72 in Time__Now () at ../src/time/POSIX/TimePosix.m3:14
#4  0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000fedf6df8: Bad address.
) at ../src/Main.m3:327
#5  0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000fedf6eb8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:449
#6  0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000fedf6f68: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:422
#7  0x000000000047c7d4 in thread_start ()
#8  0x0000000000000000 in ?? ()

Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
#0  0x000000000047e53c in _umtx_op_err ()
#1  0x0000000000475f14 in __thr_umutex_lock ()
#2  0x0000000000479404 in mutex_lock_common ()
#3  0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000feff7d98: Bad address.
) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
#4  0x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000feff7dc8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:119
#5  0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000feff7df8: Bad address.
) at ../src/Main.m3:319
#6  0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000feff7eb8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:449
#7  0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000feff7f68: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:422
#8  0x000000000047c7d4 in thread_start ()
#9  0x0000000000000000 in ?? ()

Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
#0  0x000000000047e53c in _umtx_op_err ()
#1  0x0000000000475759 in suspend_common ()
#2  0x00000000004755c1 in pthread_suspend_np ()
#3  0x000000000044df0c in ThreadPThread__SuspendThread (mt=Error accessing memory address 0x8000ffbfd6f8: Bad address.
) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
#4  0x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=Error accessing memory address 0x8000ffbfd718: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:909
#5  0x000000000044bc81 in ThreadPThread__StopWorld () at ../src/thread/PTHREAD/ThreadPThread.m3:948
#6  0x000000000044b19e in RTThread__SuspendOthers () at ../src/thread/PTHREAD/ThreadPThread.m3:713
#7  0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at ../src/runtime/common/RTCollector.m3:749
#8  0x0000000000433081 in RTCollector__CollectSome () at ../src/runtime/common/RTCollector.m3:723
#9  0x0000000000432d49 in RTHeapRep__CollectEnough () at ../src/runtime/common/RTCollector.m3:657
#10 0x000000000042ff83 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffbfd958: Bad address.
) at ../src/runtime/common/RTAllocator.m3:367
#11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ffbfda18: Bad address.
) at ../src/runtime/common/RTAllocator.m3:296
#12 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ffbfda78: Bad address.
) at ../src/runtime/common/RTAllocator.m3:143
#13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdab8: Bad address.
) at ../src/rw/Rd.m3:159
#14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdb88: Bad address.
) at ../src/rw/Rd.m3:187
#15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdbd8: Bad address.
) at ../src/rw/Rd.m3:176
#16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ffbfdc58: Bad address.
) at ../src/Main.m3:185

#17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ffbfdeb8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:449
#18 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ffbfdf68: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:422
#19 0x000000000047c7d4 in thread_start ()
#20 0x0000000000000000 in ?? ()

Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
#0  0x000000000047e53c in _umtx_op_err ()
#1  0x0000000000475f14 in __thr_umutex_lock ()
#2  0x0000000000479404 in mutex_lock_common ()
#3  0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffc678: Bad address.
) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
#4  0x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1337
---Type <return> to continue, or q <return> to quit---
#5  0x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffffc6e8: Bad address.
) at ../src/runtime/common/RTAllocator.m3:365
#6  0x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=Error accessing memory address 0x8000ffffc7a8: Bad address.
) at ../src/runtime/common/RTAllocator.m3:224
#7  0x000000000042eb23 in RTHooks__AllocateTracedObj (M3_AJWxb1_defn=Error accessing memory address 0x8000ffffc7f8: Bad address.
) at ../src/runtime/common/RTAllocator.m3:122
#8  0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=Error accessing memory address 0x8000ffffc858: Bad address.
) at ../src/text/TextCat.m3:562
#9  0x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=0x800c490b0, M3_BUgnwf_LInfo=Error accessing memory address 0x8000ffffc8f8: Bad address.
) at ../src/text/TextCat.m3:488
#10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=Error accessing memory address 0x8000ffffcbb8: Bad address.
) at ../src/text/TextCat.m3:40
#11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=Error accessing memory address 0x8000ffffcc38: Bad address.
) at ../src/Main.m3:593
#12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=Error accessing memory address 0x8000ffffcf88: Bad address.
) at ../src/runtime/common/RTLinker.m3:408
#13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing memory address 0x8000ffffd008: Bad address.
) at ../src/runtime/common/RTLinker.m3:115
#14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing memory address 0x8000ffffd028: Bad address.
) at ../src/runtime/common/RTLinker.m3:124
#15 0x00000000004004a6 in main (argc=Error accessing memory address 0x8000ffffd07c: Bad address.
) at _m3main.c:22

Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
#0  0x000000000047e53c in _umtx_op_err ()
#1  0x0000000000477e8a in check_suspend ()
#2  0x00000000004780a2 in sigcancel_handler ()
#3  <signal handler called>
#4  0x000000000047e53c in _umtx_op_err ()
#5  0x0000000000475f14 in __thr_umutex_lock ()
#6  0x0000000000479404 in mutex_lock_common ()
#7  0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ff5fac18: Bad address.
) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
#8  0x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1337
#9  0x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad address.
) at ../src/runtime/common/RTAllocator.m3:365
#10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ff5fad48: Bad address.
) at ../src/runtime/common/RTAllocator.m3:296
#11 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address.
) at ../src/runtime/common/RTAllocator.m3:143
#12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ff5fade8: Bad address.
) at ../src/Main.m3:283
#13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ff5faeb8: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:449
#14 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address.
) at ../src/thread/PTHREAD/ThreadPThread.m3:422
#15 0x000000000047c7d4 in thread_start ()
#16 0x0000000000000000 in ?? ()

(others are similar)

Hmm looks like a FreeBSD issue now.  It's here...

int
__cdecl
ThreadPThread__SuspendThread (m3_pthread_t mt)
{
  ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "pthread_suspend_np");
  return 1;
}

Now this suspend can wait:

static int
suspend_common(struct pthread *curthread, struct pthread *thread,
        int waitok)
{
        uint32_t tmp;

        while (thread->state != PS_DEAD &&
              !(thread->flags & THR_FLAGS_SUSPENDED)) {
                thread->flags |= THR_FLAGS_NEED_SUSPEND;
                /* Thread is in creation. */
                if (thread->tid == TID_TERMINATED)
                        return (1);
                tmp = thread->cycle;
                _thr_send_sig(thread, SIGCANCEL);
                THR_THREAD_UNLOCK(curthread, thread);
                if (waitok) {
                        _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, 0);  <==========
                        THR_THREAD_LOCK(curthread, thread);
                } else {
                        THR_THREAD_LOCK(curthread, thread);
                        return (0);
                }
        }

        return (1);
}

... but what it can wait for I am not clear on.

Do things work better on Linux?

What is the status of the fork bug?  Can it be worked around by only forking via Process.Create with no mutexes held (outside of all LOCK blocks)?

     Mika



Peter McKinna writes:
>--001a11c2ced4471a2e050079db82
>Content-Type: text/plain; charset=UTF-8
>
>Mika
>
>  I think you need to back out Tony's changes to fix the fork bug, at least
>for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If
>you're using git you're on your own.
>  Do a cvs log ThreadPThread.m3 for an explanation for some of the design
>principles.
>  Also if you use gdb then you need to set lanc c before backtraces so at
>least you can see address names and values even if they are contorted you
>can extract the M3 name in the parm lists. Also in gdb thread apply all bt
>gives all thread backtraces which can be handy to see whose got the locks
>held.
>
>Regards Peter
>
>
>
>On Wed, Aug 13, 2014 at 12:14 PM, <mika at async.caltech.edu> wrote:
>
>>
>> Question... is there something odd about my pthreads?  Are pthreads
>> normally reentrant?  I didn't think so.
>>
>> My compiler is much happier with the following changes I already outlined:
>>
>> 1. a dirty, disgusting hack to keep from locking against myself going from
>> XWait with self.mutex locked to m.release().
>>
>> 2. the change to LockHeap I described in previous email
>>
>> But now...
>>
>> (gdb) cont
>> Continuing.
>> ERROR: pthread_mutex_lock:11
>> ERROR: pthread_mutex_lock:11
>>
>> Program received signal SIGABRT, Aborted.
>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>> (gdb) where
>> #0  0x000000080107626a in thr_kill () from /lib/libc.so.7
>> #1  0x000000080113dac9 in abort () from /lib/libc.so.7
>> #2  0x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=Error
>> accessing memory address 0x8000ffffb508: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>> #3  0x000000000071d48d in RTOS__LockHeap () at
>> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>> #4  0x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=Error
>> accessing memory address 0x8000ffffb568: Bad address.
>> ) at ../src/runtime/common/RTCollector.m3:2234
>> #5  0x000000000071d284 in ThreadPThread__AtForkParent () at
>> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>> #6  0x0000000800df8733 in fork () from /lib/libthr.so.3
>> #7  0x000000000070dd8b in RTProcess__Fork () at
>> ../src/runtime/common/RTProcessC.c:152
>> #8  0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec
>> (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad address.
>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>> #9  0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error accessing
>> memory address 0x8000ffffb7f8: Bad address.
>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=Error
>> accessing memory address 0x8000ffffb838: Bad address.
>> ) at ../src/QMachine.m3:1666
>> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error
>> accessing memory address 0x8000ffffb9f8: Bad address.
>> ) at ../src/QMachine.m3:1605
>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error accessing
>> memory address 0x8000ffffbee8: Bad address.
>> ) at ../src/QMachine.m3:1476
>>
>> What am I doing wrong here?
>>
>> The error doesn't look unreasonable!  Looking more closely at the code:
>>
>> First, AtForkPrepare has been called:
>>
>> PROCEDURE AtForkPrepare() =
>>   VAR me := GetActivation();
>>       act: Activation;
>>   BEGIN
>>     PThreadLockMutex(slotsMu, ThisLine());
>>     PThreadLockMutex(perfMu, ThisLine());
>>     PThreadLockMutex(initMu, ThisLine()); (* InitMutex =>
>> RegisterFinalCleanup => LockHeap *)
>>     PThreadLockMutex(heapMu, ThisLine());
>>     PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers
>> => activeMu *)
>>     (* Walk activations and lock all threads.
>>      * NOTE: We have initMu, activeMu, so slots won't change, conditions
>> and
>>      * mutexes won't be initialized on-demand.
>>      *)
>>     act := me;
>>     REPEAT
>>       PThreadLockMutex(act.mutex, ThisLine());
>>       act := act.next;
>>     UNTIL act = me;
>>   END AtForkPrepare;
>>
>> a postcondition of this routine is that heapMu is locked.
>>
>> now we get into AtForkParent:
>>
>> PROCEDURE AtForkParent() =
>>   VAR me := GetActivation();
>>       act: Activation;
>>       cond: Condition;
>>   BEGIN
>>     (* Walk activations and unlock all threads, conditions. *)
>>     act := me;
>>     REPEAT
>>       cond := slots[act.slot].join;
>>       IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) END;
>>       PThreadUnlockMutex(act.mutex, ThisLine());
>>       act := act.next;
>>     UNTIL act = me;
>>     PThreadUnlockMutex(activeMu, ThisLine());
>>     PThreadUnlockMutex(heapMu, ThisLine());
>>     PThreadUnlockMutex(initMu, ThisLine());
>>     PThreadUnlockMutex(perfMu, ThisLine());
>>     PThreadUnlockMutex(slotsMu, ThisLine());
>>   END AtForkParent;
>>
>> We can see by inspecting the code that a necessary precondition for
>> this routine is that heapMu is locked!  (Since it's going to unlock it,
>> it had BETTER be locked on entry.)
>>
>> But the cond := ... causes a RTHooks.CheckLoadTracedRef
>>
>> which causes an RTOS.LockHeap
>>
>> the code of which we just saw:
>>
>> PROCEDURE LockHeap () =
>>   VAR self := pthread_self();
>>   BEGIN
>>     WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END;
>> ...
>>
>> we try to lock heapMu.  kaboom!  No surprise there, really?
>>
>> Am I going about this totally the wrong way?  Other people are running
>> Modula-3
>> with pthreads, right?  Right??  Somewhere out there in m3devel-land?
>>
>>      Mika
>>
>>
>
>--001a11c2ced4471a2e050079db82
>Content-Type: text/html; charset=UTF-8
>Content-Transfer-Encoding: quoted-printable
>
><div dir=3D"ltr">Mika<div><br></div><div>=C2=A0 I think you need to back ou=
>t Tony's changes to fix the fork bug, at least for now. Need to reload =
>from cvs version 1.262 for ThreadPThread.m3 If you're using git you&#39=
>;re on your own.</div>
>
><div>=C2=A0 Do a cvs log ThreadPThread.m3 for an explanation for some of th=
>e design principles.=C2=A0</div><div>=C2=A0 Also if you use gdb then you ne=
>ed to set lanc c before backtraces so at least you can see address names an=
>d values even if they are contorted you can extract the M3 name in the parm=
> lists. Also in gdb thread apply all bt gives all thread backtraces which c=
>an be handy to see whose got the locks held.</div>
>
><div><br></div><div>Regards Peter</div><div><br></div><div class=3D"gmail_e=
>xtra"><br><br><div class=3D"gmail_quote">On Wed, Aug 13, 2014 at 12:14 PM, =
> <span dir=3D"ltr"><<a href=3D"mailto:mika at async.caltech.edu" target=3D"=
>_blank">mika at async.caltech.edu</a>></span> wrote:<br>
>
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
>x #ccc solid;padding-left:1ex"><br>
>Question... is there something odd about my pthreads? =C2=A0Are pthreads no=
>rmally reentrant? =C2=A0I didn't think so.<br>
><br>
>My compiler is much happier with the following changes I already outlined:<=
>br>
><br>
>1. a dirty, disgusting hack to keep from locking against myself going from =
>XWait with self.mutex locked to m.release().<br>
><br>
>2. the change to LockHeap I described in previous email<br>
><br>
>But now...<br>
><br>
>(gdb) cont<br>
>Continuing.<br>
>ERROR: pthread_mutex_lock:11<br>
>ERROR: pthread_mutex_lock:11<br>
><br>
>Program received signal SIGABRT, Aborted.<br>
>0x000000080107626a in thr_kill () from /lib/libc.so.7<br>
>(gdb) where<br>
>#0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7<br>
>#1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7<br>
>#2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=3DE=
>rror accessing memory address 0x8000ffffb508: Bad address.<br>
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>#3 =C2=A00x000000000071d48d in RTOS__LockHeap () at ../src/thread/PTHREAD/T=
>hreadPThread.m3:1377<br>
>#4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=
>=3DError accessing memory address 0x8000ffffb568: Bad address.<br>
>) at ../src/runtime/common/RTCollector.m3:2234<br>
>#5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () at ../src/thr=
>ead/PTHREAD/ThreadPThread.m3:1348<br>
>#6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3<br>
>#7 =C2=A00x000000000070dd8b in RTProcess__Fork () at ../src/runtime/common/=
>RTProcessC.c:152<br>
>#8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec (M3_Bd56=
>fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Bad address.<br>
>) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>#9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError acces=
>sing memory address 0x8000ffffb7f8: Bad address.<br>
>) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>#10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=3DError=
> accessing memory address 0x8000ffffb838: Bad address.<br>
>) at ../src/QMachine.m3:1666<br>
>#11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DError access=
>ing memory address 0x8000ffffb9f8: Bad address.<br>
>) at ../src/QMachine.m3:1605<br>
>#12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError accessin=
>g memory address 0x8000ffffbee8: Bad address.<br>
>) at ../src/QMachine.m3:1476<br>
><br>
>What am I doing wrong here?<br>
><br>
>The error doesn't look unreasonable! =C2=A0Looking more closely at the =
>code:<br>
><br>
>First, AtForkPrepare has been called:<br>
><br>
>PROCEDURE AtForkPrepare() =3D<br>
>=C2=A0 VAR me :=3D GetActivation();<br>
>=C2=A0 =C2=A0 =C2=A0 act: Activation;<br>
>=C2=A0 BEGIN<br>
>=C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> Re=
>gisterFinalCleanup =3D> LockHeap *)<br>
>=C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D> S=
>uspendOthers =3D> activeMu *)<br>
>=C2=A0 =C2=A0 (* Walk activations and lock all threads.<br>
>=C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won't ch=
>ange, conditions and<br>
>=C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.<br>
>=C2=A0 =C2=A0 =C2=A0*)<br>
>=C2=A0 =C2=A0 act :=3D me;<br>
>=C2=A0 =C2=A0 REPEAT<br>
>=C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());<br>
>=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;<br>
>=C2=A0 =C2=A0 UNTIL act =3D me;<br>
>=C2=A0 END AtForkPrepare;<br>
><br>
>a postcondition of this routine is that heapMu is locked.<br>
><br>
>now we get into AtForkParent:<br>
><br>
>PROCEDURE AtForkParent() =3D<br>
>=C2=A0 VAR me :=3D GetActivation();<br>
>=C2=A0 =C2=A0 =C2=A0 act: Activation;<br>
>=C2=A0 =C2=A0 =C2=A0 cond: Condition;<br>
>=C2=A0 BEGIN<br>
>=C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditions. *)<br=
>>
>=C2=A0 =C2=A0 act :=3D me;<br>
>=C2=A0 =C2=A0 REPEAT<br>
>=C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;<br>
>=C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, This=
>Line()) END;<br>
>=C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());<br>
>=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;<br>
>=C2=A0 =C2=A0 UNTIL act =3D me;<br>
>=C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());<br>
>=C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());<br>
>=C2=A0 END AtForkParent;<br>
><br>
>We can see by inspecting the code that a necessary precondition for<br>
>this routine is that heapMu is locked! =C2=A0(Since it's going to unloc=
>k it,<br>
>it had BETTER be locked on entry.)<br>
><br>
>But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef<br>
><br>
>which causes an RTOS.LockHeap<br>
><br>
>the code of which we just saw:<br>
><br>
>PROCEDURE LockHeap () =3D<br>
>=C2=A0 VAR self :=3D pthread_self();<br>
>=C2=A0 BEGIN<br>
>=C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSE=
>RT r=3D0*> END;<br>
>...<br>
><br>
>we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, really?<br>
><br>
>Am I going about this totally the wrong way? =C2=A0Other people are running=
> Modula-3<br>
>with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in m3devel-la=
>nd?<br>
><span><font color=3D"#888888"><br>
>=C2=A0 =C2=A0 =C2=A0Mika<br>
><br>
></font></span></blockquote></div><br></div></div>
>
>--001a11c2ced4471a2e050079db82--



More information about the M3devel mailing list