libzypp: zypp-core/ng/io/process.cpp Source File

libzypp 17.38.15

process.cpp
Go to the documentation of this file.
1#include "process.h"
2#include <zypp-core/ng/io/private/asyncdatasource_p.h>
3#include <zypp-core/ng/base/EventDispatcher>
4#include <zypp-core/ng/io/private/abstractspawnengine_p.h>
5#include <zypp-core/ng/io/AsyncDataSource>
6#include <zypp-core/ng/base/private/linuxhelpers_p.h>
7#include <fcntl.h>
8
9namespace zyppng {
10
15
16 class ProcessPrivate : public AsyncDataSourcePrivate
17 {
18 public:
19 ProcessPrivate( Process &p )
20 : AsyncDataSourcePrivate(p)
21 , _sigFinished(p)
22 { }
23
24 void cleanup() {
25 _stdinFd = -1;
26 _stderrFd = -1;
27 _stdoutFd = -1;
28 }
29
30 std::unique_ptr<AbstractSpawnEngine> _spawnEngine = AbstractSpawnEngine::createDefaultEngine();
31 zypp::AutoFD _stdinFd = -1;
32 zypp::AutoFD _stderrFd = -1;
33 zypp::AutoFD _stdoutFd = -1;
34 Signal<void ()> _sigStarted;
35 MemSignal<Process, void ( int )> _sigFinished;
36 Signal<void ()> _sigFailedToStart;
37
38 Process::OutputChannelMode _channelMode = Process::Seperate;
39 Process::OutputChannel _currentChannel = Process::StdOut;
40 };
41
42 ZYPP_IMPL_PRIVATE(Process)
43
44 Process::Process() : AsyncDataSource( *( new ProcessPrivate(*this) ) )
45 {
46
47 }
48
49 Process::Ptr Process::create()
50 {
51 return std::shared_ptr<Process>( new Process() );
52 }
53
54 Process::~Process()
55 {
56 Z_D();
57 if ( d->_spawnEngine->pid() >= 0 ) {
58 EventDispatcher::instance()->untrackChildProcess( d->_spawnEngine->pid() );
59 DBG << "Process destroyed while still running removing from EventLoop." << std::endl;
60 }
61 }
62
63 bool Process::start( const char *const *argv )
64 {
65 Z_D();
66
67 if ( !EventDispatcher::instance() ) {
68 ERR << "A valid EventDispatcher needs to be registered before starting a Process" << std::endl;
69 return false;
70 }
71
72 if ( isRunning() )
73 return false;
74
75 // clean up the previous run
76 AsyncDataSource::close();
77 d->cleanup();
78
79 // create the pipes we need
80 auto stdinPipe = Pipe::create( );
81 if ( !stdinPipe ) {
82 d->_sigFailedToStart.emit();
83 return false;
84 }
85
86 auto stdoutPipe = Pipe::create( );
87 if ( !stdoutPipe ) {
88 d->_sigFailedToStart.emit();
89 return false;
90 }
91
92 int stderr_fd = -1;
93 std::optional<Pipe> stderrPipe;
94 if ( d->_channelMode == Seperate ) {
95 stderrPipe = Pipe::create( );
96 if ( !stderrPipe ) {
97 d->_sigFailedToStart.emit();
98 return false;
99 }
100 stderr_fd = stderrPipe->writeFd;
101 } else {
102 stderr_fd = stdoutPipe->writeFd;
103 }
104
105 if ( d->_spawnEngine->start( argv, stdinPipe->readFd, stdoutPipe->writeFd, stderr_fd ) ) {
106
107 // if we reach this point the engine guarantees that exec() was successful
108 const auto pid = d->_spawnEngine->pid( );
109
110 // register to the eventloop right away
111 EventDispatcher::instance()->trackChildProcess( pid, [this]( int, int status ){
112 Z_D();
113 d->_spawnEngine->notifyExited( status );
114 d->_sigFinished.emit( d->_spawnEngine->exitStatus() );
115 });
116
117 // make sure the fds we need are kept open
118 d->_stdinFd = std::move( stdinPipe->writeFd );
119 d->_stdoutFd = std::move( stdoutPipe->readFd );
120
121 std::vector<int> rFds { d->_stdoutFd };
122 if ( stderrPipe ) {
123 d->_stderrFd = std::move( stderrPipe->readFd );
124 rFds.push_back( d->_stderrFd.value() );
125 }
126
127 if ( !openFds( rFds, d->_stdinFd ) ) {
128 stop( SIGKILL );
129 return false;
130 }
131
132 d->_sigStarted.emit();
133 return true;
134 }
135 d->_sigFailedToStart.emit();
136 return false;
137 }
138
139 void Process::stop( int signal )
140 {
141 Z_D();
142 if ( isRunning() ) {
143 ::kill( d->_spawnEngine->pid(), signal );
144 }
145 }
146
147 bool Process::isRunning()
148 {
149 Z_D();
150 return ( d->_spawnEngine->pid() > -1 );
151 }
152
153 void Process::close ()
154 {
155 flush();
156 stop(SIGKILL);
157 d_func()->cleanup();
158 AsyncDataSource::close();
159 }
160
161 void Process::waitForExit()
162 {
163 Z_D();
164 if ( d->_spawnEngine->isRunning() ) {
165 // we will manually track the exit status
166 EventDispatcher::instance()->untrackChildProcess( d->_spawnEngine->pid() );
167 // wait for the process to exit
168 d->_spawnEngine->isRunning( true );
169 }
170 }
171
172 void Process::closeWriteChannel()
173 {
174 Z_D();
175 d->_stdinFd = -1;
176 AsyncDataSource::closeWriteChannel();
177 }
178
179 const std::string &Process::executedCommand() const
180 {
181 return d_func()->_spawnEngine->executedCommand();
182 }
183
184 const std::string &Process::execError() const
185 {
186 return d_func()->_spawnEngine->execError();
187 }
188
189 zypp::filesystem::Pathname Process::chroot() const
190 {
191 return d_func()->_spawnEngine->chroot();
192 }
193
194 void Process::setChroot( const zypp::filesystem::Pathname &chroot )
195 {
196 return d_func()->_spawnEngine->setChroot( chroot );
197 }
198
199 bool Process::useDefaultLocale() const
200 {
201 return d_func()->_spawnEngine->useDefaultLocale();
202 }
203
204 void Process::setUseDefaultLocale( bool defaultLocale )
205 {
206 return d_func()->_spawnEngine->setUseDefaultLocale( defaultLocale );
207 }
208
209 Process::Environment Process::environment() const
210 {
211 return d_func()->_spawnEngine->environment();
212 }
213
214 void Process::setEnvironment( const Process::Environment &env )
215 {
216 return d_func()->_spawnEngine->setEnvironment( env );
217 }
218
219 pid_t Process::pid()
220 {
221 return d_func()->_spawnEngine->pid();
222 }
223
224 int Process::exitStatus() const
225 {
226 return d_func()->_spawnEngine->exitStatus();
227 }
228
229 bool Process::dieWithParent() const
230 {
231 return d_func()->_spawnEngine->dieWithParent();
232 }
233
234 void Process::setDieWithParent( bool enabled )
235 {
236 return d_func()->_spawnEngine->setDieWithParent( enabled );
237 }
238
239 bool Process::switchPgid() const
240 {
241 return d_func()->_spawnEngine->switchPgid();
242 }
243
244 void Process::setSwitchPgid(bool enabled)
245 {
246 return d_func()->_spawnEngine->setSwitchPgid( enabled );
247 }
248
249 zypp::filesystem::Pathname Process::workingDirectory() const
250 {
251 return d_func()->_spawnEngine->workingDirectory();
252 }
253
254 void Process::setWorkingDirectory(const zypp::filesystem::Pathname &wd)
255 {
256 return d_func()->_spawnEngine->setWorkingDirectory( wd );
257 }
258
259 const std::vector<int> &Process::fdsToMap() const
260 {
261 return d_func()->_spawnEngine->fdsToMap();
262 }
263
264 void Process::addFd(int fd)
265 {
266 return d_func()->_spawnEngine->addFd( fd );
267 }
268
269 int Process::stdinFd()
270 {
271 return d_func()->_stdinFd;
272 }
273
274 int Process::stdoutFd()
275 {
276 return d_func()->_stdoutFd;
277 }
278
279 int Process::stderrFd()
280 {
281 return d_func()->_stderrFd;
282 }
283
284 SignalProxy<void ()> Process::sigStarted()
285 {
286 return d_func()->_sigStarted;
287 }
288
289 SignalProxy<void ()> Process::sigFailedToStart()
290 {
291 return d_func()->_sigFailedToStart;
292 }
293
294 SignalProxy<void (int)> Process::sigFinished()
295 {
296 return d_func()->_sigFinished;
297 }
298
299 Process::OutputChannelMode Process::outputChannelMode() const { return d_func()->_channelMode; }
300 void Process::setOutputChannelMode(const OutputChannelMode &outputChannelMode) { d_func()->_channelMode = outputChannelMode; }
301
302}
DBG
#define DBG
Definition Logger.h:129
ERR
#define ERR
Definition Logger.h:132
abstractspawnengine_p.h
asyncdatasource_p.h
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zyppng::AbstractSpawnEngine::createDefaultEngine
static std::unique_ptr< zyppng::AbstractSpawnEngine > createDefaultEngine()
Definition abstractspawnengine.cc:64
zyppng::AsyncDataSourcePrivate::AsyncDataSourcePrivate
AsyncDataSourcePrivate(AsyncDataSource &pub)
Definition asyncdatasource_p.h:14
zyppng::AsyncDataSource::close
void close() override
Definition asyncdatasource.cpp:260
zyppng::AsyncDataSource::AsyncDataSource
AsyncDataSource()
Definition asyncdatasource.cpp:139
zyppng::AsyncDataSource::openFds
bool openFds(const std::vector< int > &readFds, int writeFd=-1)
Definition asyncdatasource.cpp:152
zyppng::AsyncDataSource::closeWriteChannel
virtual void closeWriteChannel()
Definition asyncdatasource.cpp:283
zyppng::AsyncDataSource::flush
void flush()
Definition asyncdatasource.cpp:334
zyppng::EventDispatcher::instance
static std::shared_ptr< EventDispatcher > instance()
Definition eventdispatcher_glib.cc:629
zyppng::MemSignal
Definition signals.h:160
zyppng::ProcessPrivate
Definition process.cpp:17
zyppng::ProcessPrivate::_spawnEngine
std::unique_ptr< AbstractSpawnEngine > _spawnEngine
Definition process.cpp:30
zyppng::ProcessPrivate::_stdinFd
zypp::AutoFD _stdinFd
Definition process.cpp:31
zyppng::ProcessPrivate::_sigFailedToStart
Signal< void()> _sigFailedToStart
Definition process.cpp:36
zyppng::ProcessPrivate::_stderrFd
zypp::AutoFD _stderrFd
Definition process.cpp:32
zyppng::ProcessPrivate::ProcessPrivate
ProcessPrivate(Process &p)
Definition process.cpp:19
zyppng::ProcessPrivate::_currentChannel
Process::OutputChannel _currentChannel
Definition process.cpp:39
zyppng::ProcessPrivate::_channelMode
Process::OutputChannelMode _channelMode
Definition process.cpp:38
zyppng::ProcessPrivate::cleanup
void cleanup()
Definition process.cpp:24
zyppng::ProcessPrivate::_stdoutFd
zypp::AutoFD _stdoutFd
Definition process.cpp:33
zyppng::ProcessPrivate::_sigFinished
MemSignal< Process, void(int)> _sigFinished
Definition process.cpp:35
zyppng::ProcessPrivate::_sigStarted
Signal< void()> _sigStarted
Definition process.cpp:34
zyppng::Process
Definition process.h:32
zyppng::Process::switchPgid
bool switchPgid() const
Definition process.cpp:239
zyppng::Process::outputChannelMode
OutputChannelMode outputChannelMode() const
Definition process.cpp:299
zyppng::Process::Environment
std::map< std::string, std::string > Environment
For passing additional environment variables to set.
Definition process.h:38
zyppng::Process::chroot
zypp::Pathname chroot() const
Definition process.cpp:189
zyppng::Process::~Process
~Process() override
Definition process.cpp:54
zyppng::Process::dieWithParent
bool dieWithParent() const
Definition process.cpp:229
zyppng::Process::close
void close() override
Definition process.cpp:153
zyppng::Process::exitStatus
int exitStatus() const
Definition process.cpp:224
zyppng::Process::Process
Process()
Definition process.cpp:44
zyppng::Process::setEnvironment
void setEnvironment(const Environment &environment)
Definition process.cpp:214
zyppng::Process::stop
void stop(int signal=SIGTERM)
Definition process.cpp:139
zyppng::Process::closeWriteChannel
void closeWriteChannel() override
Definition process.cpp:172
zyppng::Process::executedCommand
const std::string & executedCommand() const
Definition process.cpp:179
zyppng::Process::addFd
void addFd(int fd)
Definition process.cpp:264
zyppng::Process::OutputChannelMode
OutputChannelMode
Definition process.h:42
zyppng::Process::Seperate
@ Seperate
Definition process.h:43
zyppng::Process::create
static Ptr create()
Definition process.cpp:49
zyppng::Process::start
bool start(const char *const *argv)
Definition process.cpp:63
zyppng::Process::isRunning
bool isRunning()
Definition process.cpp:147
zyppng::Process::useDefaultLocale
bool useDefaultLocale() const
Definition process.cpp:199
zyppng::Process::waitForExit
void waitForExit()
Definition process.cpp:161
zyppng::Process::setWorkingDirectory
void setWorkingDirectory(const zypp::Pathname &workingDirectory)
Definition process.cpp:254
zyppng::Process::sigStarted
SignalProxy< void()> sigStarted()
Definition process.cpp:284
zyppng::Process::Ptr
ProcessRef Ptr
Definition process.h:39
zyppng::Process::stderrFd
int stderrFd()
Definition process.cpp:279
zyppng::Process::fdsToMap
const std::vector< int > & fdsToMap() const
Definition process.cpp:259
zyppng::Process::setUseDefaultLocale
void setUseDefaultLocale(bool defaultLocale)
Definition process.cpp:204
zyppng::Process::setSwitchPgid
void setSwitchPgid(bool enabled)
Definition process.cpp:244
zyppng::Process::stdinFd
int stdinFd()
Definition process.cpp:269
zyppng::Process::pid
pid_t pid()
Definition process.cpp:219
zyppng::Process::setChroot
void setChroot(const zypp::Pathname &chroot)
Definition process.cpp:194
zyppng::Process::setOutputChannelMode
void setOutputChannelMode(const OutputChannelMode &outputChannelMode)
Definition process.cpp:300
zyppng::Process::OutputChannel
OutputChannel
Definition process.h:47
zyppng::Process::StdOut
@ StdOut
Definition process.h:48
zyppng::Process::stdoutFd
int stdoutFd()
Definition process.cpp:274
zyppng::Process::workingDirectory
zypp::Pathname workingDirectory() const
Definition process.cpp:249
zyppng::Process::setDieWithParent
void setDieWithParent(bool enabled)
Definition process.cpp:234
zyppng::Process::sigFailedToStart
SignalProxy< void()> sigFailedToStart()
Definition process.cpp:289
zyppng::Process::sigFinished
SignalProxy< void(int)> sigFinished()
Definition process.cpp:294
zyppng::Process::environment
Environment environment() const
Definition process.cpp:209
zyppng::Process::execError
const std::string & execError() const
Definition process.cpp:184
zyppng::SignalProxy
Definition signals.h:325
zyppng::Signal
Definition signals.h:151
linuxhelpers_p.h
zyppng::env
Definition repomanager.cc:53
zyppng
Definition MediaNetworkRequestExecutor.h:16
zyppng::ZYPP_IMPL_PRIVATE
ZYPP_IMPL_PRIVATE(UnixSignalSource)
process.h
zypp::AutoFD
AutoDispose<int> calling close
Definition AutoDispose.h:310
zyppng::Pipe::create
static std::optional< Pipe > create(int flags=0)
Definition linuxhelpers.cc:71
Z_D
#define Z_D()
Definition zyppglobal.h:98