pthread em tempo real criado a partir de thread não em tempo real com init.d

4

Eu tenho um código C ++ que roda bem quando eu o executo a partir de um terminal Linux, mas que gera um erro EPERM quando executado a partir de um script SystemV (init.d) no bootup . O erro vem de um pthread_create com o seguinte bit de atributos atribuídos ao thread que está tentando ser criado:

pthread_t reading_thread;

pthread_attr_t read_attr;
struct sched_param read_param; 
pthread_attr_init(&read_attr);
pthread_attr_setschedpolicy(&read_attr, SCHED_FIFO);
pthread_attr_setinheritsched(&read_attr, PTHREAD_EXPLICIT_SCHED);
read_param.sched_priority = 30;
pthread_attr_setschedparam(&read_attr, &read_param);

k = pthread_create(&reading_thread, &read_attr, Reading_Thread_Function, 
            (void*) &variable_to_pass_to_Reading_Thread_Function); // Will return EPERM

Este código funciona bem quando executado a partir do meu terminal. Ele também funciona bem no script init.d quando eu chamo "/etc/init.d/myinitdscript start". Ele também funciona bem como "sudo service myinitdscript start". O script init.d contém o seguinte:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          myinitdscript
# Required-Start:    $local_fs $remote_fs $syslog $network
# Required-Stop:     $local_fs $remote_fs $syslog $network
# Default-Start:     3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts my daemon
# Description:       Verbose explanation of starting my daemon
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin
LOG=/home/someusershome/initd.log
NAME=myinitdscript
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
[ -x "$DAEMON" ] || (echo "$DAEMON not found. Exiting $SCRIPTNAME." >> $LOG 2>&1 && exit 0)
USERTORUNAS=a_user_on_my_system
SOURCE_SCRIPT=/home/$USERTORUNAS/source_script
DAEMON_ARGS="some_args_for_script"

. /lib/init/vars.sh

. /lib/lsb/init-functions

# Source this script for environmental variables
[ -f $SOURCE_SCRIPT ] && . $SOURCE_SCRIPT

# This is called when called with 'start', I am skipping that for succintness
do_start()
{
    start-stop-daemon --start --make-pidfile --pidfile $PIDFILE --test --background --chuid $USERTORUNAS --startas /bin/bash -- -c "exec $DAEMON -- $DAEMON_ARGS >> $LOG 2>&1 " || return 1
    start-stop-daemon --start --make-pidfile --pidfile $PIDFILE --background --chuid $USERTORUNAS --startas /bin/bash -- -c "exec $DAEMON -- $DAEMON_ARGS >> $LOG 2>&1" || return 2
}

Se eu ativar este script init.d usando:

update-rc.d myinitdscript defaults 99

ocorrerá erro na inicialização com um erro EPERM lançado na chamada pthread_create (k = 1, aka EPERM). Eu posso rodar isso usando o serviço mydoitdscript start do sudo, e ele rodará bem. Eu também posso chamar o /etc/init.d/myinitdscript start, e ele funcionará bem. É somente quando deixo o sistema executar este script na inicialização que ele falha.

Eu acho que se eu adicionar ao meu start-stop-daemon chama a opção "-P fifo: 99" Eu não recebo o erro EPERM e o código roda bem, exceto em uma prioridade muito alta, então eu não vou chame isso de correção. A única parte do código que precisa ser executada em tempo real é que o pthread foi criado a partir do código. Então, suponho que isso tenha a ver com minhas permissões para criar um thread em tempo real com prioridade 30 a partir de um thread normalmente agendado.

Por que meu script precisa de diretivas / prioridades de agendamento especiais quando executado da inicialização versus quando eu inicio manualmente o script init.d ou por meio de serviço?

EDIT: rodando no Ubuntu 12.04.

EDIT2: Eu tentei adicionar uma chamada para "ulimit -r" dentro do meu código que a chamada start-stop-daemon inicia, e eu fico ilimitado, então, até onde eu posso ver, não deve haver nenhum problema de permissão indo com SCHED_FIFO: 30 lá

EDIT3: Acontece que estou executando o Upstart e o Upstart possui um script de inicialização chamado rc-sysinit.conf, que inicia todos os scripts de estilo SystemV. Então talvez o Upstart esteja estragando minhas permissões.

    
por codemonkey851232 08.10.2016 / 01:10

1 resposta

2

A resposta parece ter sido colocar o seguinte no meu script init.d, que eu coloquei antes das chamadas start-stop-daemon em do_start:

ulimit -r ## (where ## is a sufficiently high number; 99 works)

A maneira como consegui determinar isso foi fazendo chamadas de sistema para ulimit -a dentro de um comando bash dentro do meu código:

bash -c "ulimit -a"

A parte bash é necessária, porque ulimit -a é um shell embutido. ulimit -a on / bin / sh retorna informações diferentes não relacionadas à prioridade em tempo real. Por algum motivo, descobri que minha prioridade em tempo real estava limitada a 0 (sem prioridade em tempo real) quando meu serviço é iniciado na inicialização. Quando eu o executo com o serviço ou chamando o script init.d, ele herda minhas permissões que permitem a prioridade em tempo real. Mas quando o sistema o chama através do sistema de compatibilidade com versões anteriores do Upstart / SystemV, ele não obtém esse privilégio elevado. Suponho que isso possa estar relacionado a postagens que eu vi que dizem que o Upstart não lê o /etc/security/limits.conf, que é onde você deve definir as permissões de prioridade em tempo real do sistema para usuários sem privilégios.

Se alguém puder verificar ou explicar por que essa solução funciona, adoraria ouvi-la.

    
por 11.10.2016 / 18:53