Solaris 11.4, acme, thread library problem

9 views
Skip to first unread message

Noel Hunt

unread,
Feb 20, 2026, 5:15:06 PM (3 days ago) Feb 20
to plan9port-dev
I have just installed plan9port on the current Solaris release, but there
are problems with what appears to be the threads library. I discovered this
by running a command in an acme tag line, a trivial 'echo foobar' will exhibit
the problem. The +Errors window reports a segmentation violation, a dbx trace
shows the following:

$ dbx /opt/plan9/bin/acme core
Reading acme
core file header read successfully
Reading ld.so.1
Reading libm.so.2
Reading librt.so.1
Reading libpthread.so.1
Reading libsocket.so.1
Reading libnsl.so.1
Reading libthread.so.1
Reading libc.so.1
t@20 (l@20) program terminated by signal SEGV (no mapping at the fault address)
Current function is _threadspawn
   83                   dup2(fd[0], 0);
(dbx) where
current thread: t@20
=>[1] _threadspawn(fd = 0xfd46cdc4, cmd = 0x8110490 "echo", argv = 0x80fa918, dir = 0x8114f80 "/opt/plan9/src/cmd/htmlfmt"), line 83 in "exec.c"
  [2] execproc(v = 0xfd46cb50), line 15 in "exec.c"
  [3] procmain(p = 0x8114380), line 254 in "thread.c"
  [4] startprocfn(v = 0x80fa260), line 99 in "pthread.c"
  [5] _thrp_setup(0xfe4b9240), at 0xfe2a9bd9
  [6] _lwp_start(0x0, 0x0, 0x0, 0xd, 0x10, 0x0), at 0xfe2a9ec0
(dbx) (dbx) up
Current function is execproc
   15           pid = _threadspawn(e->fd, e->cmd, e->argv, e->dir);
(dbx) (dbx) print *e
dbx: cannot access address 0xfd46cb50
(dbx) (dbx) up
Current function is procmain
  254           t->startfn(t->startarg);
(dbx) (dbx) print *t
*t = {
    next       = (nil)
    prev       = (nil)
    allnext    = (nil)
    allprev    = (nil)
    startfn    = 0x80aec20 = &`acme`libthread/exec.c`execproc(void *v)
    startarg   = 0xfd46cb50
    id         = 20U
    osprocid   = 0
    stk        = (nil)
    stksize    = 0
    exiting    = 0
    mainthread = 1
    proc       = 0x8114380
    name       = ""
    state      = ""
    udata      = (nil)
    chanalt    = (nil)
    schedrend  = {
        l      = (nil)
        asleep = 0
        cond   = {
            __pthread_cond_flags = {
                __pthread_cond_flag  = ""
                __pthread_cond_type  = 0
                __pthread_cond_magic = 0
            }
            __pthread_cond_data  = 0
        }
    }
}
(dbx) (dbx) print *t->startarg
*t->startarg = (void)


I can find no documentation or references to _thrp_setup and _lwp_start, no prototypes
even in system include files, so I have no idea where this is coming from.

Noel Hunt

Russ Cox

unread,
8:29 AM (12 hours ago) 8:29 AM
to noel...@gmail.com, plan9port-dev
_thrp_setup and _lwp_start are Solaris symbols involved in creating a new thread. It makes sense that they would be at the top of the stack. 

In 2020, I changed libthread to stop doing all the shenanigans we used to do about our own thread stacks, stack switching, and so on. It's all standard pthread use now, so it really should work. The only thing I can think of is that execproc is started with an argument that points to the original pthread's stack. That thread waits for execproc to say it is done before returning, so it should be okay to do that. But maybe Solaris does not let one pthread see another's stack. You could try replacing _runthreadspawn in src/lib/thread/exec.c with this:

int
_runthreadspawn(int *fd, char *cmd, char **argv, char *dir)
{
        int pid;
        Execjob *e;

        e = mallocz(sizeof *e, 1);
        e->fd = fd;
        e->cmd = cmd;
        e->argv = argv;
        e->dir = dir;
        e->c = chancreate(sizeof(void*), 0);
        proccreate(execproc, e, 65536);
        pid = recvul(e->c);
        chanfree(e->c);
        free(e);
        return pid;
}

Best,
Russ

Reply all
Reply to author
Forward
0 new messages