I am coding on Windows, so fork() is not available. Now, i need to run execl(), but it is an end point of my program! I thought of creating a separate thread to run execl(), which is created successfully, and runs well also. But still my program comes to an end after thread is over.
Function running thread--It is inside class wScoreget:-
int refresh_score_now(){
pthread_t t;
if(pthread_create(&t,NULL,s.basicgetscore,&s)==-1){
printf("Error: wScoreget:3");
exit(4);
}
void *a;
if(pthread_join(t,&a)==-1){
printf("Error: wScoreget: 4");
exit(4);
printf("Running thread.\n");
getch();
}
}
Calling from main:-
int main(){
wScoreget new_ws;
new_ws.refresh_score_now();
printf("reached to the end\n");
getch();
}
I am expecting console to print- "reached to the end"
But on execl() it exits.
NOTE: execl() is running curl. Its output is going to a text file. Now, if stdout is changed, curl shows download timing and other data on the console. THAT data comes to console anyways.
Is there a way I can do this without using CreateProcess? And if I use CreateProcess, which libraries do I have to install on Windows(I am using MingW + Codeblocks).
Try using spawn or posix_spawn. It should replace fork + exec.
http://en.wikipedia.org/wiki/Spawn_%28computing%29
http://linux.die.net/man/3/posix_spawn
Related
I have a problem with my C code, basically I need to send email via mutt program. It must be send when an interrupt comes up from GPIO pin. My sendMail function is listed below. I realized this by using system function. Main contains loop with logAlarm func which contains sendMail. The thing is when system(cmd) function finishes, the whole C program stops. For instance when i put sendMail function at the begining of the main it works and is sending email to my mailbox without stopping whole program, in the loop it manages to send it but it terminates program. I tried to using & sign to run it in background but it didnt help.
P.S i dont know if it matters but im also using system call from setitimer with 2 sec intervals to check few things but i guess it has no impact for this case.
Any ideas?
Thanks in advance :)
sendMail function:
void sendMail(char * msg, char * recipientMail){
char cmd[100];
char subject[30];
char body[60];
sprintf(body, "Intruder detected!!!\n%s", msg);
strcpy(subject, "\"ALARM - SECURITY BREACH\"");
sprintf(cmd,"echo \"%s\" | mutt -s %s %s &", body, subject, recipientMail);
printf("%s\n\n", cmd);
system(cmd);
}
Here is a piece of my main function:
while(1){
sleep(1);
if(prev_state == triggered && !emailDetach){
if(!logAlarm()){
printf("Error writing to log file!!!\n");
}
emailDetach = true;
}
//printf("Czas od poprzedniego alarmu: %d", millis() - alarmTriggeredTime);
if((prev_state == triggered) && (millis() - alarmTriggeredTime >= ALARM_TIME)){
digitalWrite(ALARM_ON_DIODE, LOW);
digitalWrite(ALARM_OFF_DIODE, HIGH);
//warunek czasowy osobno na syrene TODO
if(!silentMode && (millis() - alarmTriggeredTime >= siren_alarm_time)){
digitalWrite(SIREN, LOW);
}
prev_state = nottriggered;
}
}
Good question. As per description, I consider that sendMail function works properly. I've not worked with mutt. But i've worked with system().
What system does is, it forks a child process of your current process and executes the command using execve(). So the problem should be in the returning of the system.
So, first you should check the return status of system function. If you are able to make printf() below the system(), then you're not having problem with system(). If you are not able get printf below the system(), then system() is killing your process. (by sending sigkill or similer signals, but not sigint or sigquit, since it is ignored by system()). You are creating a child process in the cmd itself (echo output piping to mutt). May be this should be root cause.
If you find problem here, then the problem is critical, and you will find directions from the "NOTES" section of "man system", since you have implemented the same logic mentioned there. First just try to wait for conditions mentioned there. If you're still unable to do this, try to fork two new child process, run execl or any other exec family function ("man 3 exec") from that child process to run echo and mutt.
If system() is ok, then check logAlarm(). is it giving the right arguments to the sendMail? if you are getting "Error writing to log file!!!", then entire sequence is ok.
I am executing LSF and Perl files (which have specific function related to automation of test cases) from my c function. I want to execute the system() command and dont want to wait till the process of execution of the files is complete, instead I want the control to fall back to the main c program to continue with the execution of the program and leave the task to be carried out by the linux execution engine.can someone help me with this.
I have attached the code below:
sprintf(String, "/home/teproj/nxp90884/CellDesign/AN_DFIIToCdl.lsf %s %s %s %s %s", res, cel, tmp, frc, upd);
system(String);
Since system() forks a shell to run your command line, you can just append an ampersand (&) to the command line to make the shell run the command in the background.
That's the quick and dirty approach. The clean approach is of course to do the process management yourself, using fork() and exec() calls.
You can fork and call the execve system call in the child process, continuing with your original job in the parent process(or vice-versa)
To run a task in the background you need to start a new thread. fork() is one friend, the pthread family another.
Example using fork:
process = fork();
if (process < 0){
//fork error
perror("fork");
exit(EXIT_FAILURE);
}
if (process == 0){
// Child process. You can either use one of the exec functions:
execl("/home/teproj/nxp90884/CellDesign/AN_DFIIToCdl.lsf" "AN_DFIIToCdl.lsf", res, cel, tmp,frc,upd, NULL);
// or system + exit.
sprintf(String, "c %s %s %s %s %s", res, cel, tmp, frc, upd);
system(String);
exit(0); // to terminate the child.
} else {
// Main thread. Continue executing
}
Best practice is to choose one of the exec functions in this case.
I am seeing a strange issue.
Sometimes when i run my program long enough i see that there are two copies of my program running. The second is a child process of the first since i see that the parent PID of the second one is that of the first one.
I realized that i have a fork in my code and its only because of this that i can have two copies running -- i can otherwise never have two copies of my program running.
This happens very rarely but it does happen.
The architecture is as follows:
The main program gets an event and spawns a pthread. In that thread i do some processing and based on some result i do a fork immediately followed by an execvp.
I realize that its not best to call a fork from a pthread but in my design the main process gets many events and the only way to parallely work on all those events was to use pthreads. Each pthread does some processing and in certain cases it needs to call a different program (for which i use execvp). Since i had to call a different program i had to use fork
I am wondering if because i am eventually calling a fork from a thread context is it possible that multiple threads parallely call fork + execvp and this "somehow" results in two copies being created.
If this is indeed happening would it help if i protect the code that does fork+execvp with a mutex since that would result in only one thread calling the fork + execvp.
However, if i take a mutex before fork + excvp then i dont know when to release it.
Any help here would be appreciated.
thread code that does fork + execvp -- in case you guys can spot an issue there:
In main.c
status = pthread_create(&worker_thread, tattr,
do_some_useful_work, some_pointer);
[clipped]
void *do_some_useful_work (void * arg)
{
/* Do some processing and fill pArguments array */
child_pid = fork();
if (child_pid == 0)
{
char *temp_log_file;
temp_log_file = (void *) malloc (strlen(FORK_LOG_FILE_LOCATION) +
strlen("/logfile.") + 8);
sprintf (temp_log_file, "%s/logfile.%d%c", FORK_LOG_FILE_LOCATION, getpid(),'\0');
/* Open log file */
int log = creat(temp_log_file, 0777);
/* Redirect stdout to log file */
close(1);
dup(log);
/* Redirect stderr to log file */
close(2);
dup(log);
syslog(LOG_ERR, "Opening up log file %s\n", temp_log_file);
free (temp_log_file);
close (server_sockets_that_parent_is_listening_on);
execvp ("jazzy_program", pArguments);
}
pthread_exit (NULL);
return NULL;
}
I looked through this code and i see no reason why i would do a fork and not do an execvp -- so the only scenario that comes to my mind is that multiple threads get executed and they all call fork + execvp. This sometimes causes two copies of my main program to run.
In the case where execvp fails for any reason (perhaps too many processes, out of memory, etc.), you fail to handle the error; instead the forked copy of the thread keeps running. Calling pthread_exit (or any non-async-signal-safe) function in this process has undefined behavior, so it might not exit properly but hang or do something unexpected. You should always check for exec failure and immediately _exit(1) or similar when this happens. Also, while this probably isn't your problem, it's unsafe to call malloc after forking in a multithreaded process since it's non-async-signal-safe.
I have the following code:
for (loop=0;loop<2;loop++)
{
child_pid = fork();
if (child_pid == 0)
{
rc = execvp ("/usr/local/some_program", arguments);
}
}
I change the arguments passed to /usr/local/some_program based on the value of loop. I want the some_program to parallel-ly execute two instances. But i see that i first execute some_program once and only after it finishes that i get execute the second instance of some_program.
I not able to get them to run parallelly and independently.
Instead of fork, should i use pthreads?
The some_program that i am trying to execute is completely unrelated to the parent process.
Thanks
"I not able to get them to run parallelly and independently." - No. Both process will be executed in parallel. To check that create two programs like this-
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
printf("Pid= %d\n", getpid());
while(1);
}
Compile those 2 program's and make two executable files. Pass these 2 exe file names via command line arguments to main program and run that using system command.But your main program should be live.
for (loop=0;loop<2;loop++)
{
child_pid = fork();
if (child_pid == 0)
{
system(argv[loop+1]);
exit(0); // if you don't use exit your second exe file will be executed twice.
}
}
while(1);
Now type ps command in terminal and find the TTY name and run the main program. Open a new terminal and type
ps -e | grep pts/X // pts/X is main program running terminal name. it may pts/0 or pts/1 ...
Through this you can come to know that the two processes running parallelly or not.
In Linux, readline() in an infinite loop repeatdly reads text\n. However, as soon as child processes start printing to the screen, readline no longer reads new lines. Even if I repeatdly press enter, readline() doesn't return.
Anyone know what's wrong?
Code sample as requested:
char* input;
int cpid;
while(1)
{
input = readline(">>>");
strcpy(tempInput, input); //...does some stuff w/ tempInput
//....
cpid = fork();
if(cpid == 0){
printf("..."); printf("...");
execl("ls", "ls", "-l", (char*) NULL); //sample execl parameters
}
else{
//do some stuff...
printf("...");
}
free(input);
}
//readline(">>>") works the first time and doesn't return on subsequent calls
The stacktrace of where the code hangs (forever):
Thread [1] (Suspended : Signal : SIGINT:Interrupt)
__read_nocancel() at ../sysdeps/unix/syscall-template.S:82 0x7ffff78f0490
rl_getc() at 0x7ffff7bc3727
rl_read_key() at 0x7ffff7bc3c90
readline_internal_char() at 0x7ffff7baf25f
readline() at 0x7ffff7baf795
main() at /home/.../.../xxx.c:95 0x4010a1
Edit: This probably sounds like total technobabble to experienced unix developers, but could the child process have somehow 'captured' stdin and fail to release it somehow?
Your child processes, even after exec, still has its standard input connected to your terminal. Either use wait() to wait for the child process to finish, or reopen the child's standard input as /dev/null:
close(STDIN_FILENO) && open("/dev/null", "O_WRONLY");
After you fork(), your child process executes the 2 printf calls, then goes on to execute the while(1) loop, so what you are doing is creating 1 extra process after every newline.
What you need to do, is kill the child immediately after it prints the 2 ellipses (...)
Change your code to this:
if(cpid == 0){
printf("..."); printf("..."); exec(...); exit(0);
}
Bear in mind, exit() is called only if the exec() fails.
Edit:
If you intend to accept input for some kind of command line interpreter, readline isn't a very good option. Its official man page says:
BUGS:
It’s too big and too slow.
I could suggest an alternative way of getting the input string:
char c;
inputString = calloc(0,sizeof(char));
inputLength = 0;
c = getchar();
while(c!='\n')
{
inputString = realloc(inputString,(inputLength+1)*sizeof(char));
inputString[inputLength++] = c;
c = getchar();
}
inputString[inputLength] = '\0';
Now you have the string in inputString & its length in inputLength. You could very well do:
execlp(inputString,inputString,0);
to execute the required functionality.
This piece of code is not working because your call to execl() is failing, therefore the child process will resume at the loop code, which will also be using readline().
You must pass the full path to the executable when using execl(), or use the execlp() variant (which search into PATH environment variable) for it to work.
Even for the simplest syscalls, it's a good practice to always check for their return codes.