I have a main program (in C) which needs to branch out into lua_thread(the main continues to run).This lua_thread calls a lua_script.lua. this lua_script contains a while loop. a lua variable controls this while loop.Currently this loop runs forever.
lua_script.lua
--this loop runs forever, as the exit value is not set yet
a=0
while(a<=0)
do
print("value of a:", a)
end
My goal is to change this lua variable(a) from main program such that it exits this infinite loop. Once this loop ends, it exits the thread and returns to the main program.
main.c
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
void *lua_thread()
{
int status, result;
double sum;
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
status = luaL_loadfile(L, "lua_script.lua");
if (status)
{
fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));
exit(1);
}
result = lua_pcall(L, 0, 0, 0);
if (result) {
fprintf(stderr, "Failed to run script: %s\n", lua_tostring(L, -1));
exit(1);
}
lua_close(L);
return 0;
}
int main(void)
{
pthread_t p1;
pthread_create(&p1,NULL,lua_thread,NULL);
pthread_join(p1,NULL);
return 0;
}
If you run the above code
cc -o xcute main.c -I/usr/include/lua5.2 -llua -lm -ldl -pthread
it will go into an infinite loop. I want to somehow control the lua variable and change it to a=1,from the main program so that it comes out of the infinite loop.
the reason for doing such a test is that it will make sure that before the main program exits, this thread exits first by controlling the lua variable.
Please suggest how to change this lua variable so that it exits the while loop.
Interacting with a running lua state from a different thread is not necessarily safe so modifying the script's global variable may or may not be a useful idea depending on where you are planning to be making that change from the C side.
If you wanted to do this you would simply need to use the lua C api to set the global variable of the appropriate name in the appropriate lua state.
An alternate idea would be to create a should_exit global function which is called at the start or end of every loop and when it returns true causes the lua code to break or return. This function can then check anything it wants to on the C side in whatever thread-appropriate manner is desired.
Why to have this loop in Lua? You may loop in c-thread instead, lua_pcalling some entry-point function (e.g. onEvent()) on each iteration.
If loop has to be in Lua script, for example in case of setup-loop-cleanup scheme, you may run script in coroutine and use coroutine.yield() as loop condition. Thread should lua_resume() with true value or exit depending on your c-side condition. (Or resume with false if Lua-side cleanup after the loop is preferred.)
Anyway, Lua is not thread-safe and cannot be called simultaneously from more than one thread.
Oh, you went hard way in your answer (sure that was a great exercise though). Things could be much simpler:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static volatile int shouldRun = 1; // 1.
static int
fn_sleep(lua_State *L)
{
lua_Integer n = luaL_checkinteger(L, 1);
sleep(n < 0 ? 0 : n);
return 0;
}
static int
fn_shouldRun(lua_State *L)
{
lua_pushboolean(L, shouldRun);
return 1;
}
static void *
thread_main(void *dummy)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_register(L, "sleep", fn_sleep); // 2.
lua_register(L, "shouldRun", fn_shouldRun);
if (luaL_dofile(L, "script.lua")) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L); // 3.
return 0;
}
int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_create(&thread, NULL, thread_main, NULL);
sleep(5);
shouldRun = 0; // 1.
pthread_join(thread, NULL);
return 0;
}
script.lua:
print("Hi!")
while shouldRun() do
print("Running!")
sleep(1)
end
print("Bye!")
output:
Hi!
Running!
Running!
Running!
Running!
Running!
Bye!
Few things to note:
Polled exit conditions usually do not need any protection. If shouldRun() was called simultaneously with variable update and missed it, then nothing to worry about – it will return false next time. Anyway, you can't even guess where the script is executing, just [re]set the value and wait for completion.
For a pair of specific functions there is no need to write a require/preload-compatible module. Export them into global namespace instead.
For graceful close on error do not just exit(). lua_close() will garbage-collect all userdata used by script, and their __gc metamethod may do something useful like flushing buffers to disk, etc. You lose all chances with hard exit.
It took me two days to come up with this. Hopefully,it will help someone to save sometime.
main.c
#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
#include <fcntl.h>
#include <semaphore.h>
void *lua_thread(void *arg)
{
int status, result, i;
double sum;
lua_State *L=(lua_State *)arg;
int a=0;
status = luaL_dofile(L, "lua_script.lua");
if (status) {
fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));
exit(1);
}
printf("Lua thread exiting\n");
return 0;
}
int main(void)
{
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
//Open semaphore which will signal Lua loop to exit
sem_t *lex=sem_open("luaexitsem", O_CREAT, 0600, 0);
//Make sure value of the semaphore is 0 before we start running
//so that sem_post sets it to 1 later
int retval;
for(retval=0;retval==0;) {
retval=sem_trywait(lex);
printf("Dec sem val: %d\n", retval);
}
//Start Lua thread
pthread_t p1;
pthread_create(&p1,NULL,lua_thread,L);
sleep(5);
//Signal Lua script to exit
sem_post(lex);
//Wait for Lua thread to exit
pthread_join(p1,NULL);
//Cleanup
printf("Main exiting\n");
lua_close(L);
sem_close(lex);
return 0;
}
To compile
gcc -o main main.c -I/usr/include/lua5.1 -llua5.1 -lm -ldl -pthread
lua_script.lua
require "lualinuxthread"
a=1
while(not linuxthread.signaltoexit())
do
print("value of a:", a)
a=a+1
end
lualinuxthread.c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include <semaphore.h>
#include <errno.h>
#include <fcntl.h>
static int signaltoexit(lua_State *L) {
sem_t *lex=sem_open("luaexitsem", O_CREAT, 0600, 0);
int exitvalue=0, retval;
if (lex!=SEM_FAILED)
retval=sem_trywait(lex);
if (retval==-1) exitvalue=0; else exitvalue=1;
printf("signaltoexit - exitvalue: %d, retval: %d, %x\n", exitvalue, retval, lex);
lua_pushboolean(L, exitvalue);
sem_close(lex);
return 1;
}
static const luaL_Reg libfuncs[] = {
{"signaltoexit", signaltoexit},
{NULL, NULL}
};
LUALIB_API int luaopen_lualinuxthread (lua_State *L) {
luaL_register(L, "linuxthread", libfuncs);
return 1;
}
to compile:
gcc -O -O2 -fpic -shared lualinuxthread.c -o lualinuxthread.so -lpthread -llua5.1
Thank you
Related
I am recently learning about threads in C, and I have noticed something I consider weird.
Let's take the next code:
#include <stdio.h>
#include <pthread.h>
void *sub_routine(void *p)
{
p = NULL;
printf("This is a sub_routine\n");
return (NULL);
}
int main(int argc, char **argv)
{
void *p;
pthread_t thread;
if (argc < 1)
return (0);
p = argv[1];
pthread_create(&thread, NULL, sub_routine, NULL);
sub_routine(p);
return (0);
}
I use this command line to compile my program:
gcc -Wall -Wextra -Werror -pthread pthreads.c
The expected result is to print This is a sub_routine two times. Well that happens but not 100% of the times. Is there any particular reason for that?
When main returns, it exits the program even if other threads are running. Therefore, it’s possible for the thread you spawned to not get to the printf before the main thread returns, in which case the program ends before you’ll see both messages.
One way to address this is to add a call to pthread_join at the end of main to tell the program to wait for the thread you created to finish running before main returns. That will ensure you always see two printouts.
Add pthread_join(thread, NULL) at the end (just before return) of the main thread to join the thread "sub_routine"
The modified version of your code works properly:
#include <stdio.h>
#include <pthread.h>
void *sub_routine(void *p)
{
p = NULL;
printf("This is a sub_routine\n");
return (NULL);
}
int main(int argc, char **argv)
{
void *p;
pthread_t thread;
if (argc < 1)
return (0);
p = argv[1];
pthread_create(&thread, NULL, sub_routine, NULL);
sub_routine(p);
pthread_join(thread, NULL);
return (0);
}
I have written quite a lot of threaded code on HP-UX and even SUSE and that works perfectly. But it does not work on Red Hat. This is my machine:
Linux version 3.10.0-1062.18.1.el7.x86_64 (Red Hat 4.8.5-39)
Red_Hat_Enterprise_Linux-Release_Notes-7-en-US-7-2.el7.noarch
redhat-release-server-7.7-10.el7.x86_64
I wrote a simple test program, thr_ex.c:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void *funny(void *);
void *funny(s)
void *s;
{
int fd;
fd = creat("/tmp/funny_func", 0600);
write(fd, s, strlen((char *) s));
close(fd);
}
int main()
{
int return_value;
pthread_t thread_id;
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
return_value = pthread_create(&thread_id, &thread_attr, funny, (void *) "Here I am\n");
printf("Return value == %d\n", return_value);
printf("Thread id == %hu\n", thread_id);
exit(0);
} /* End main. */
Compiling, building:
gcc -pthread -s -o thr_ex thr_ex.c
Running:
./thr_ex
Return value == 0
Thread id == 5888
But no file gets created under /tmp.
strace -f shows no creat() or write() ( except from the printf's in main () ).
However, strace -f do show, for example:
strace: Exit of unknown pid 64574 ignored
I have tried even simpler code where the thread only runs a printf() and a fflush(), with no thread attributes and no argument to the function. Still nothing happens.
Insert before the return statement or exit( 0 ) statement in main
pthread_exit( NULL );
Otherwise the created thread can have no time to be executed because the process will end.
I am trying to make a program that takes several files, appends them all into one big file. Each append has to be done by a separate thread.
/*
This program creates appends several files together
*/
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
pthread_t *tids;
void *threadout(void *num);
int main(int argc, char *argv[])
{
int numOfFiles = atoi(argv[2]);
int error;
int index;
sem_t sem;
//Used for output file
int outFile;
//Checking to make sure there is the correct number of arguments
if (argc != 4)
{
printf("%s \n", "Wrong number of arguments, exiting program.");
return 1;
}
//checking to make sure there are at least two files to append
if (numOfFiles < 2)
{
printf("%s \n", "Cannot append 1 file or less.");
return 1;
}
//opening/creating file
outFile = open(argv[3], O_WRONLY | O_CREAT, S_IRUSR);
///****************** Allocate space for thread ids ******************/
tids = (pthread_t *)calloc(numOfFiles, sizeof(pthread_t));
if (tids == NULL)
{
perror("Failed to allocate memory for thread IDs");
return 1;
}
if (sem_init(&sem, 0, 1) == -1)
{
perror("Failed to initialize semaphore");
return 1;
}
/****************** Create threads *********************************/
for (index = 0; index < numOfFiles; index++)
{
if (error = pthread_create(tids + index, NULL, threadout, &index))
{
fprintf(stderr, "Failed to create thread:%s\n", strerror(error));
return 1;
}
}
return 0;
}
void * threadout(void *num)
{
printf("Hello");
return NULL;
}
Near the bottom of the program I do the actual creating of the threads. The first thing the thread should do is hit the "threadout" function. However the only way I can get anything to print is if I say to create a large number of threads. So if I tell my program to create 5000 threads, "Hello" will be printed. Not 5000 times though. If I asked it to create 10 threads nothing is printed. Am I doing something wrong when I invoke "threadout"? Thanks
Returning from main causes your entire program to exit, even if other threads are running.
Your main function exits when all threads are started. If you're starting lots of threads, this leaves enough time for the first ones to print. If you're starting few threads, it returns before the first ones get to print anything.
You might want to use pthread_join (called once per thread) to wait for all threads to terminate.
I've spent quite a few hours on trying to figure this one out and I'm completly stuck. The program is supposed to start 6 threads. Where some threads start where others end. Right now, I'm trying to get one single thread (thread 0) to execute. The caps lock commenting shows where I have added code and done my mistakes. My main struggle here is dealing with the pointers. Could anyone give me any pointers (ha..ha.. :c )?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define SHARED 1
sem_t sem[6];
struct threadargs
{
int id; /* thread number */
int sec; /* how many sec to sleep */
int signal[6]; /* which threads to signal when done */
};
void *tfunc(void *arg)
{
int i;
struct threadargs *targs=arg;
sem_wait(sem); //WAIT FOR OWN SEMAPHORE
printf("Thread %d is running\n", targs->id);
sleep(targs->sec);
printf("Thread %d is completed and may wake others..\n", targs->id);
for(i=0; i<6; i++) //ITERATE OVER signal_ARRAY &
{ //WAKE THREAD NUMBER i IF
if(targs->signal[i] == 1) //signal[i] IS 1
pthread_cond_signal(&sem[i]);
}
}
int main(void)
{
int i, j;
struct threadargs *targs[6];
pthread_t tid[6];
for(i=0; i<6; i++)
{
targs[i] = (struct threadargs*) malloc(sizeof(struct threadargs));
for(j=0; j<6; j++)
{ targs[i]->signal[j]=0; }
}
targs[0]->id=1;
targs[0]->sec=1;
targs[0]->signal[1]=1;
targs[0]->signal[4]=1;
sem[0] = 0; //INITIALIZE THREAD'S SEMAPHORE TO 0 or 1
pthread_create(targs[0], NULL, tfunc, NULL) // START THREAD
for(i=0; i<6; i++)
pthread_join(tid[i], NULL);
return 0;
}
Alright. First things first, I do recommend taking a second look at your coding style. It is of course highly subjective and I won't say yours is bad, but it took me a while to figure it out (if you really want to know, I recommend the Linux coding style for C/C++ code).
Lets get on with your problem. As far as I can see, the main issue seems that you're basically comparing pointers to apples with pointers to banana's (in other words, you're using the wrong pointer type in the wrong place).
To make sure that calls to functions and the like are correct, make sure to look up the API documentation for functions that are new to you (examples: pthread_create, sem_init, sem_wait, sem_post, pthread_cond_signal).
As you can see, pthread_cond_signal doesn't take a sem_t* as argument, and therefore you can't pass one to it and expect it to work. Below you'll find an example program showing how semaphores are used.
First, a new thread is created which will be put in waiting state instantly. As soon as the main tread finished counting from 0 to 150, it will post ('unlock') the semaphore and allowing the second thread to finish its execution.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t sem_thread_one;
static pthread_t thread_one_data;
static int x;
static void *tfunc(void *arg)
{
sem_wait(&sem_thread_one);
printf("Thread 1 is running. The value of x is %i\n", x);
return NULL;
}
int main(int argc, char **argv)
{
sem_init(&sem_thread_one, 0 /* don't share between processes */, 0);
if(pthread_create(&thread_one_data, NULL, &tfunc, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
while(x < 150) {
x++;
}
sem_post(&sem_thread_one);
if(pthread_join(thread_one_data, NULL)) {
fprintf(stderr, "Could not join threads, exiting!\n");
return -EXIT_FAILURE;
}
sem_destroy(&sem_thread_one);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file sem.c and compile & link using:
gcc -Wall -Os -pthread -o sem_test sem.c
Now a second example, but now using pthread_cond_t. The functionality of the program is somewhat similar, it waits for a counter to reach a certain number.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
static pthread_t thread_one_data, thread_two_data;
static volatile int x, y, idx = 10;
static int count = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
static void *cond_test_wait(void *arg)
{
pthread_mutex_lock(&mutex);
while(count < 10) {
printf("Waiting for `count < 10' to become true\n");
pthread_cond_wait(&condition, &mutex);
}
pthread_mutex_unlock(&mutex);
printf("Test wait thread finished. Value of count: %i\n", count);
return NULL;
}
static void *cond_test_signal(void *arg)
{
while(count < 10) {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
/* do more intelligent things here */
count++;
pthread_mutex_unlock(&mutex);
}
printf("Test signal thread finished\n");
return NULL;
}
int main(int argc, char **argv)
{
if(pthread_create(&thread_one_data, NULL, &cond_test_wait, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
if(pthread_create(&thread_two_data, NULL, &cond_test_signal, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
pthread_join(thread_one_data, NULL);
pthread_join(thread_two_data, NULL);
pthread_cond_destroy(&condition);
pthread_mutex_destroy(&mutex);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file cond.c and compile & link using:
gcc -o cond -pthread -Os -Wall cond.c
Do note how neat condition work in this example. You can use them to wait until any expression (= condition) becomes true. After the condition becomes true normal execution continue's.
If you need any more help, don't hesitate to ask in the comments. Good luck combining the above examples to fix up your program.
I'm attempting to write a C program in OSX that will change another program's execution flow, exactly like a debugger would. But before I put all of the "pieces" together, I need to test that each of them work individually first.
I've successfully used mach_vm_read_overwrite() and mach_vm_write() to read and write to the stack.
I've successfully used thread_get_state() and thread_set_state() to read and write to registers.
All that's left is to use thread_create_running() to create a thread in the task to execute my arbitrary function. However, whenever I create a thread, OSX completely crashes and automatically reboots my computer, lol. Can someone explain what is going on in more detail?
Here's my remote program, test.c:
#include <unistd.h>
#include <stdio.h>
void function1() {
printf("lol 1\n");
}
void function2() {
printf("lol 2\n");
}
void function3() {
printf("lol 3\n");
}
int main(int argc, char **argv) {
while(1) {
function1();
sleep(1);
function2();
sleep(1);
function3();
sleep(1);
}
return 0;
}
And here's my tiny debugger-in-progress:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdint.h>
#include <mach/mach_traps.h>
#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach.h>
#include <mach/mach_types.h>
#include <mach/i386/thread_status.h>
void error(char *msg) {
printf("error: %s\n", msg);
exit(1);
}
int main(int argc, char **argv) {
pid_t pid;
mach_port_t eq_task;
kern_return_t err;
thread_act_port_array_t thread_list;
mach_msg_type_number_t thread_count;
x86_thread_state_t x86_state;
mach_msg_type_number_t sc = x86_THREAD_STATE_COUNT;
thread_act_t remoteThread;
// Make sure we have an argument
if (argc != 2)
error("requires a PID");
else
pid = (pid_t)atoi(argv[1]);
// Make sure we're root
if (getuid() && geteuid())
error("requires root");
// Get the task port
err = task_for_pid(mach_task_self(), pid, &eq_task);
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(eq_task))
error("getting eq task");
// Suspend the process
if(task_suspend(eq_task))
error("suspending the task");
// Get a list of threads from the port
if (task_threads(eq_task, &thread_list, &thread_count))
error("cannot get list of tasks");
// Get the registers
if (thread_get_state(thread_list[0], x86_THREAD_STATE, (thread_state_t)&x86_state, &sc))
error("getting state from thread");
// Create a new thread
err = thread_create_running(eq_task, x86_THREAD_STATE, (thread_state_t)&x86_state, x86_THREAD_STATE_COUNT, &remoteThread);
// BLACK SCREEN AND CRASH
// Resume the process again
if(task_resume(eq_task))
error("resuming the task");
}
I would assume that your trying to execute this in an XD bit, unless your running rocking an AMD instead of an intel. Then it would be NX opposed to XD. This would cause the application or even the entire computer to crash.