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

mika at async.caltech.edu mika at async.caltech.edu
Wed Aug 13 04:14:01 CEST 2014


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




More information about the M3devel mailing list