setsid() and process group weirdness.

Hi. I’m porting a QNX 4 app to Neutrino. I have a program that does
approximately the following:

int main()
{
// parse command line

// put ourselves in background. Under QNX 4, this was a call to
// fork() followed by a call to setsid(). I can no longer do the
// fork() because this process is multithreaded.
//fork();
setsid();

// attach name
name_attach(NULL, “faac/program”, 0);

// create a thread
pthread_create(…network_listener…);

// tons of other stuff
}

void *network_listener(void *)
{
// this hangs if I have setsid() enabled; works fine if setsid()
// is commented out. I need the coid in order to send pulses.
coid = name_open(“faac/program”);
}


If I leave the setsid call in, the name_open hangs. If I comment out
the setsid, things function more or less as I expect. Why?

Attached is the source to a short program that duplicates the problem,
as well as a shell script to start it (if the program is started
directly from shell, setsid fails because the process is already a leader).

I’m sure there are other cleaner, more Neutrino-ish ways of doing this;
what I have so far is more-or-less a direct translation of the QNX 4 code.

In a somewhat related problem in a different process, spawn() seems to
fail if I add the SPAWN_SETGROUP flag. Has anyone else gotten this to work?

In a more general sense, how exactly are sessions and process groups
handled in a multithreaded environment? If a signal is laid on a
session leader, do all threads within all processes in that session also
get the signal?

Josh Hamacher
FAAC Incorporated

Ping?

Josh Hamacher wrote:

Hi. I’m porting a QNX 4 app to Neutrino. I have a program that does
approximately the following:

int main()
{
// parse command line

// put ourselves in background. Under QNX 4, this was a call to
// fork() followed by a call to setsid(). I can no longer do the
// fork() because this process is multithreaded.
//fork();
setsid();

// attach name
name_attach(NULL, “faac/program”, 0);

// create a thread
pthread_create(…network_listener…);

// tons of other stuff
}

void *network_listener(void *)
{
// this hangs if I have setsid() enabled; works fine if setsid()
// is commented out. I need the coid in order to send pulses.
coid = name_open(“faac/program”);
}


If I leave the setsid call in, the name_open hangs. If I comment out
the setsid, things function more or less as I expect. Why?

Attached is the source to a short program that duplicates the problem,
as well as a shell script to start it (if the program is started
directly from shell, setsid fails because the process is already a leader).

I’m sure there are other cleaner, more Neutrino-ish ways of doing this;
what I have so far is more-or-less a direct translation of the QNX 4 code.

In a somewhat related problem in a different process, spawn() seems to
fail if I add the SPAWN_SETGROUP flag. Has anyone else gotten this to
work?

In a more general sense, how exactly are sessions and process groups
handled in a multithreaded environment? If a signal is laid on a
session leader, do all threads within all processes in that session also
get the signal?

Josh Hamacher
FAAC Incorporated

\

#include <pthread.h
#include <stdio.h
#include <stdlib.h
#include <unistd.h
#include <sys/dispatch.h

void *thread_one(void *);

int main(int argc, char *argv[])
{
if (argc > 1) {
if (setsid() == -1) {
fprintf(stderr, “setsid failed\n”);
exit(EXIT_FAILURE);
}
}

if (name_attach(NULL, “faac/setsid”, 0) == NULL) {
fprintf(stderr, “name_attach failed\n”);
exit(EXIT_FAILURE);
}

if (pthread_create(NULL, NULL, thread_one, NULL) != 0) {
fprintf(stderr, “pthread_create failed\n”);
exit(EXIT_FAILURE);
}

sleep(3);

fprintf(stderr, “bye\n”);

return 0;
}

void *thread_one(void *)
{
int coid;

fprintf(stderr, “calling name_attach()\n”);
if ((coid = name_open(“faac/setsid”, 0)) == -1) {
fprintf(stderr, “name_attach failed\n”);
exit(EXIT_FAILURE);
}
fprintf(stderr, “name_attach() succeeded\n”);

return NULL;
}


\

#!/bin/sh

if [ $# -ge 1 ]; then
echo Running bad…
./setsid bad &
else
echo Running good…
./setsid &
fi

If I leave the setsid call in, the name_open hangs. If I comment out
the setsid, things function more or less as I expect. Why?

This seems to be an issue, I’ll put in a bug report for a future release.


I’m sure there are other cleaner, more Neutrino-ish ways of doing this;
what I have so far is more-or-less a direct translation of the QNX 4
code.

If all you want is to put the process into the background check out daemon()
or procmgr_daemon().

In a more general sense, how exactly are sessions and process groups
handled in a multithreaded environment? If a signal is laid on a
session leader, do all threads within all processes in that session also
get the signal?

Signals and threads are a mess to combine, but essentially, a good start is
to set the sigmask for all threads (including main()) to mask out all
signals. The one remaining thread should be setup to sigwait() for a set of
signals you wish to handle and dispatch the handlers for each signal in a
syncronous manner.

If a signal is applied to a process group leader, you can have the signal
broadcast to other members of that group by using the negative value of the
pid. Signals are not broadcast to members (ie. groups) of a session, except
when a session leader is gone/killed - in which case processes of the sames
session receive a SIGHUP AFAIK.

-Adam