1

This question is exactly the opposite of Non-blocking version of system()

I want to substitute the current process by another one (not create another one).

I want to start (for instance) notepad, but in a blocking way (I don't want to get the prompt until notepad is closed.

In the Windows shell I just do

cmd /c notepad

(notepad auto-detachs from prompt if not prefixed by cmd /c)

In C, using system I just do

system("notepad");

But this is forking behind the scenes. I want to replace the current process by notepad, and I want it to be blocking.

I have tried:

#include <stdio.h>
#include <unistd.h>

int main(int argc,char **argv)
{
  char * const args[] = {"cmd","/c","notepad",NULL};
  execvp(args[0],args);
}

notepad runs, but the console returns to the prompt immediately.(non-blocking). I want it to block, and I don't want to use fork as it would create another process: I want to replace the current process.

(I have tried with a custom blocking executable, and it doesn't block either. So cmd /c notepad example is as good as any other one)

So, If I run this executable I just built from a parent process:

  • I don't want the process to return to the parent process until the notepad process exits
  • I want to be able to get output from the command (notepad isn't a good example in that case)
  • I don't want to create an extra process (this is part of a massive multiprocessing application, we can't afford to create 2 processes, we need to keep 1 process for each run)

Is it even possible?

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • Why are you exec-ing "cmd" rather than just "notepad" directly? – Lee Daniel Crocker Apr 09 '18 at 16:12
  • What is "blocking"? If you "substitute" the process, what will get blocked then? – Eugene Sh. Apr 09 '18 at 16:17
  • *I want to replace the current process by notepad* - what you mean under *replace* ?! – RbMm Apr 09 '18 at 17:01
  • *I don't want the process to return to the parent process until the notepad process exits* - this is absolute impossible in windows. but you can wait for child process exit. in what is problem ? – RbMm Apr 09 '18 at 17:19
  • call `CreateProcessW` and wait on it handle in place. however this is not very good - wait in place, always better continue execution self, instead wait, and do some task when child terminated – RbMm Apr 09 '18 at 17:20
  • I want to replace the current process, the way `execvp` replaces (doesn't create a _child_ process). It works but the process then returns to the shell and keeps running; I want it to block. – Jean-François Fabre Apr 09 '18 at 18:50
  • This is an [XY Problem](http://xyproblem.info). What are you *really* trying to accomplish? Keep in mind, that you *will* be able to afford 2 processes, once you find out, that there is no API (or native API) call in Windows, that 'replaces' a process. This also sounds like premature optimization. You don't have a proof-of-concept implemented, so there is no way, that you have actually profiled, whether that is fast enough. If it isn't, it stands to reason, that your architecture is pathological, one way or another. – IInspectable Apr 09 '18 at 19:03
  • again - what you mean under **replace** ? *execvp replaces (doesn't create a child process)* - really ? – RbMm Apr 09 '18 at 20:09
  • yes, `_execvp` (Microsoft API) does exactly that: https://msdn.microsoft.com/en-us/library/3xw6zy53.aspx. But detaches from the console that was running the "original" program. This console I want to keep "blocked". And I cannot seem to achieve this without creating a subprocess. – Jean-François Fabre Apr 09 '18 at 20:11
  • 2
    You are reading something into the [documentation](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/execvp-wexecvp), that's not there. Specifically, *"[e]ach of these functions loads and executes a **new process**"*. I'm not sure how you interpret that to mean, that the currently running process were replaced. That's not what's happening, and that's not what the documentation says either. – IInspectable Apr 09 '18 at 21:13
  • 1
    @Jean-FrançoisFabre *This console I want to keep "blocked". And I cannot seem to achieve this without creating a subprocess.* That's because **something** has to block waiting for your new process. Since nothing in the OS does that, you do have to create a child process so the original process can block and wait for the child process to exit. – Andrew Henle Apr 10 '18 at 09:54
  • When compiling, always enable the warnings, then fix those warnings The posted code code causes the compiler to output several warning messages. 1) unused parameter `argc` 2) unused parameter `argv[]` 3) implicit declaration of function `execvp()` (due to missing header: `unistd.h`) 4) the second parameter to `execvp()` should be declared as `char * const args[] ///' not `const char * args[]` – user3629249 Apr 11 '18 at 15:41
  • ok, fixed. But the question is still unanswered (I doubt it will be) – Jean-François Fabre Apr 11 '18 at 15:47

1 Answers1

3

It's not exactly clear what you want - the current process can't wait on the child process if it's replaced by the child executable via an execv*() function.

A possible system() replacement - on Windows - is _spawnvp():

intptr_t _spawnvp(  
   int mode,  
   const char *cmdname,  
   const char *const *argv   
);  

Just use

int rc = _spawnvp( _P_WAIT, command, args );

(I suspect the reason this exact functionality isn't available on POSIX systems is that it's easily implemented on POSIX via fork(), exec*(), and a variation of wait(). Windows equivalents of those are a bit more complex.)

One thing to be careful of when using Windows _spawn*() functions is filenames with spaces in them. I've had some real issues passing such filenames via this function and had to quote them.

Community
  • 1
  • 1
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • 1
    Just a note for other viewers...this is a Windows-only thing. – Lee Daniel Crocker Apr 09 '18 at 16:12
  • 1
    The UNIX equivalent would be [`posix_spawn`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html). –  Apr 09 '18 at 17:34
  • @Jean-FrançoisFabre, if you're looking to reliably couple this spawned process to the current process, even if the current process is terminated, then assign it to a Job object that's configured to kill-on-close and allow silent breakaway. (Prior to Windows 8 a process can only be assigned to a single Job. If you use `CreateProcess` you can flag the create to break away from the current Job, if possible.) – Eryk Sun Apr 09 '18 at 23:38