popen w Linuksie vs. popen w Mac OS

0

Cześć,
mam problem z działaniem funkcjo popen pod tymi dwoma systemami (zapożyczone z Stack Overflow, wcześniej próbowałem z innymi kombinacjami, też z popen):

string Utils::exec(const string &cmd) {
    DEBUG("Exec: " + cmd);
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);

    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != NULL)
            result += buffer.data();
    }

    return result;
}

Pod Linuksem kod wykonuje się poprawnie i zwraca output polecenia, które tak wywołuje. W Mac os'ie wygląda to tak, jakby polecenie uruchamiało się w tle, a swój stdout przekierowywało mimo wszystko do konsoli. Powyższe exec gubi się wtedy i zwraca zwykle pusty string, przez co program się wysypuje.

Macie jakieś pomysły jak to można usprawnić?

Maciek

0

A jak to działa ze zwykłym hello worldem?

0
Azarien napisał(a):

A jak to działa ze zwykłym hello worldem?
uruchomienie tego na samym początku main'a daje oczekiwany efekt, nawet ze sleepem w poleceniu. Jeśli odpalę po uruchomieniu innych wątków w programie, to jest kilka opcji:

  1. output z popen (ewentualny log z programu) pojawia się po jego zakończeniu - po nowym znaku zachęty z bash'a (wykonuje echo terefere):
II void DConfig::open(const string &)(57683)[dconfig.cpp:18]: Loading configuration file from ./config.dinemic
DD int main(int, char **)(57683)[main.cpp:55]: Initializing drivers
II ZeroMQSync::ZeroMQSync(StoreInterface *)(57683)[sync/zeromqsync.cpp:12]: Creating ZeroMQSync
ZeroMQSync created at tcp://0.0.0.0:59521
DD ZeroMQSync::ZeroMQSync(StoreInterface *)(57683)[sync/zeromqsync.cpp:26]: ZeroMQSync created at tcp://0.0.0.0:59521
DD string Utils::exec(const string &)(57683)[utils.cpp:49]: Exec: /bin/ls -1 /tmp/update_*
DD string Utils::exec(const string &)(57684)[utils.cpp:49]: Exec: /bin/ls -1 /tmp/update_*
ls: /tmp/update_*: No such file or directory
DD string Utils::exec(const string &)(57683)[utils.cpp:49]: Exec: sleep 1 ; echo terefere
ls: /tmp/update_*: No such file or directory
DD string Utils::exec(const string &)(57684)[utils.cpp:49]: Exec: sleep 1 ; echo terefere
EE int main(int, char **)(57683)[main.cpp:61]: 'terefere
'
maciek@MacBook-Pro-Maciek ~/C/l/tests> EE int main(int, char **)(57684)[main.cpp:61]: 'terefere
'
  1. output pojawia się dwa razy, po sobie, ale przed promptem bash'a
  2. znaki w outpucie programu są losowo poprzestawiane:
II void DConfig::open(const string &)(57728)[dconfig.cpp:18]: Loading configuration file from ./config.dinemic
DD int main(int, char **)(57728)[main.cpp:55]: Initializing drivers
II ZeroMQSync::ZeroMQSync(StoreInterface *)(57728)[sync/zeromqsync.cpp:12]: Creating ZeroMQSync
ZeroMQSync created at tcp://0.0.0.0:59523
DD ZeroMQSync::ZeroMQSync(StoreInterface *)(57728)[sync/zeromqsync.cpp:26]: ZeroMQSync created at tcp://0.0.0.0:59523
DD string Utils::exec(const string &)(57728)[utils.cpp:49]: Exec: /bin/ls -1 /tmp/update_*
DD string Utils::exec(const string &)(57729)[utils.cpp:49]: Exec: /bin/ls -1 /tmp/update_*
ls: /tmp/update_*: No such file or directory
DD string Utils::exec(const string &)(57728)[utils.cpp:49]: Exec: sleep 1 ; echo terefere
ls: /tmp/update_*: No such file or directory
DD string Utils::exec(const string &)(57729)[utils.cpp:49]: Exec: sleep 1 ; echo terefere
EE int main(int, char **)(57728)[main.cEppE: 6i1n]t:  m'atienr(eifnetr,e
c'har
 **)(57729)[main.cpp:61]: 'terefere
'

... ale tylko od wywołania mojego exec. Logi (output programu) nie powinny pisać równolegle - mają mutexy. Powyższe trzy występują najczęściej i tylko przy exec'u, który poprzednio wkleiłem. Wcześniejszy ls pochodzi z drugiego wątku. W Linuksie wszystko działa dobrze, ale nie wiem czy to kwestia przypadku, czy systemu

0
Azarien napisał(a):

A jak to działa ze zwykłym hello worldem?

Znalazłem bug'a :) W pewnym miejscu, w wątku driver'a wykonywałem fork i exec. Pod mac os'em nie miałem dostępnego avahi, z którego korzysta driver. Przez to po nieudanym execu, w procesie potomnym cały program szedł równolegle i robił problemy podczas testów - przez to były dwa outputy, pliki magicznie znikały lub pojawiały się.

Lekcja na dzisiaj - sprawdzać co zwróci systemowy execl :) albo po prostu czy przejdzie do dalszego kodu i dać awaryjnie exit

1 użytkowników online, w tym zalogowanych: 0, gości: 1