I have a little problem here. I know Linux limits the number of threads of an user can actually run.
I'm using pthread_create and an array of pthread_t limited with 50 ( pthread_t tid[50]; ). I have a for cycle that each time that limit reaches 50 every thread on pthread_t array is killed.
How? I tested almost everything. with pthread_kill(tid[w],SIGKILL); w is a simple cycle control variable goes from 0 to 50. I already tested pthread_cancel(tid[w]); and the problem keeps.
So what is the problem?
Everytime I reach 380 thread number I can't create more. But I'm killing with cancel or kill. So what is happening?
The objective of the program is a network scanner. To be faster I need like 500 threads with like 2 seconds of timeout to test IP's and ports.
Anyone knows how to "go arround" this problem?
I thought that I could kill the thread it would solve the problem but I was wrong :(
Without use ulimit or in /proc/sys/kernel/threads_max changing values, I looked at pthread_attr_setstacksize but I'm a bit confused :P
any ideas?
EDIT
The code as requested :P
I'm going to put ALL code here:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#ifndef SOL_TCP
#define SOL_TCP 6
#endif
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT 18 //retry
#endif
#define MAX_TH 250
struct ar_stc{
char* ip;
int port;
};
char* ret[2];
int porar[2];
pthread_t tid[MAX_TH];
void create_port_scan_th(char* host,int p,int j);
//cares about args.
//this is not helpful for the threads post on stackoverflow. skip this function
char** arguments_handle(int argc,char **arg)
{
char p[]="-p";
char h[]="-h";
size_t _p,_h;
_p=(size_t)strlen(p);
_h=(size_t)strlen(h);
if(argc!=5)
{
printf("Usage:./file -p PORT-RANGE -h HOST.IP\n");
exit(1);
}
if(strncmp(arg[1],p,_p)==0 || strncmp(arg[1],h,_h)==0 && strncmp(arg[3],p,_p)==0 || strncmp(arg[3],h,_h)==0)
{
if(strncmp(arg[1],p,_p)==0)
{
strncpy(ret[0],arg[2],strlen(arg[2]));
}
else
{
strncpy(ret[1],arg[2],strlen(arg[2]));
}
if(strncmp(arg[3],h,_h)==0)
{
strncpy(ret[1],arg[4],strlen(arg[4]));
}
else
{
strncpy(ret[0],arg[4],strlen(arg[4]));
}
}
return ret;
}
int* take_ports(char *arg)
{
char* ports[2];
ports[0] = malloc(5);
ports[1] = malloc(5);
memset(ports[0],0,5);
memset(ports[1],0,5);
char tmp[5];
int len = strlen(arg);
int i,j=0,x=0;
char min_p[5],max_p[5];
for(i=0;i<len;i++)
{
if(arg[i]=='-')
{
min_p[x]='\0';
j=1;
x=0;
continue;
}
else
{
if(j==0)
min_p[x]=arg[i];
else
max_p[x]=arg[i];
}
x++;
}
max_p[x]='\0';
porar[1]=atoi(max_p);
porar[0]=atoi(min_p);
free(ports[0]);
free(ports[1]);
return porar;
}
void *check_port(void* ar_p)
{
struct ar_stc *ar =ar_p;
char* ip = ar->ip;
int port = ar->port;
int s,conexao;
int timeout = 1000; //1 second timeout
s=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in dst;
setsockopt(s,SOL_TCP,TCP_USER_TIMEOUT,(char*)&timeout,sizeof(timeout)); //NOT WORKING :(
if(s<0)
{
printf("\nCouldnt create socket\nPremissions maybe?\n");
exit(1);
}
dst.sin_family = AF_INET;
dst.sin_port = htons(port);
dst.sin_addr.s_addr = inet_addr(ip);
bzero(&(dst.sin_zero),8);
//printf("\nChecking: %d...",port);
conexao = connect(s,(struct sockaddr*)&dst,sizeof(dst));
if(conexao <0)
{
printf("TCP/%d:CLOSED!\n",port); //just to make sure the thread is running
close(s);
return;
}
else
{
printf("TCP/%d:OPEN!\n",port);
close(s);
return;
}
}
int main(int argc, char **argv)
{
int open_ports[65535];
int open_ports_count=0;
int min_p,max_p;
int* p;
ret[0] = malloc(20);
ret[1] = malloc(20);
memset(ret[0],0,20);
memset(ret[1],0,20);
char** ipnport;
ipnport = arguments_handle(argc,argv);
printf("The IP is :%s and the range is %s\n",ipnport[1],ipnport[0]);
p=take_ports(ipnport[0]);
min_p=p[0];
max_p=p[1];
printf("Min port:%d e max port:%d\n",min_p,max_p);
int i;
int thread_count=-1;
for(i=min_p;i<=max_p;i++)
{
thread_count++;
create_port_scan_th(ipnport[1],i,thread_count);
if(thread_count>=MAX_TH)
{
sleep(1);
thread_count=0;
int w;
for(w=0;w<=MAX_TH;w++)
{
pthread_kill(tid[w],SIGKILL);
}
}
}
free(ret[0]);
free(ret[1]);
return 0x0;
}
void create_port_scan_th(char* host,int p,int j)
{
int error;
struct ar_stc *ar;
ar = malloc(sizeof(*ar));
ar->ip=host;
ar->port=p;
error = pthread_create(&(tid[j]),NULL,&check_port,(void*)ar);
if(error!=0)
printf("\nError creating thread:%s\n",strerror(error));
}
But I'm killing with cancel or kill.
First of all, pthread_kill does not kill or end a thread.
(see more at pthread_kill doesnt kill thread C linux or When to use pthread_cancel and not pthread_kill).
If you send SIGKILL to a thread, the entire process will end.
To end a thread, you need to
Make the thread end.
by returning from the thread function, or
calling pthread_exit or
pthread_cancel the thread
Dispose the resources tied to the thread by:
Call pthread_join() on the thread or
make the thread a detached thread.
If you opt for the last point by making the thread detached - which will automatically release the thread when it ends , you can call pthread_detach(pthread_Self()) at the start of your thread function.
Or supply a pthread_attr_t when you call pthread_create(), where you set the thread to a detached state.
As for the total number of threads you can use, linux have a limit on the total number of threads/processes any user can have running.
You can view this with the command ulimit -u
Related
I have a function that starts an aio_read task and returns to the main program.
I want to periodically check if the task is completed to close the file descriptor and maybe notify the user.
My current approach is declaring a struct that contains the struct aiocb of the task and the file descriptor. Adding it to a global array and checking if any task is working with the following (aio_check function):
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <aio.h>
#include <unistd.h>
#include "aioqueue.h"
void aio_add(struct aiocb a, int fd) {
for (int i = 0; i < MAX; i++) {
if (aio_array[i].valid == 0) {
aio_pack tmp;
tmp.cb = a;
tmp.fd = fd;
tmp.valid = 1;
aio_array[i] = tmp;
printf("request enqueued\n");
return;
}
}
printf("This shell cannot keep track of so many IO operations :/ \n");
}
void aio_check() {
for (int i = 0; i < MAX; i++) {
// wait until the request has finished
if(aio_array[i].valid) {
if (aio_error(&aio_array[i].cb) != EINPROGRESS) {
int nleidos = aio_return(&aio_array[i].cb);
if (nleidos != -1)
printf("AIO Task finished: %d B\n", nleidos);
else
printf("Error!");
close(aio_array[i].fd);
aio_array[i].valid = 0;
} else {
printf("At least one AIO task is in progress\n");
}
}
}
}
and the code for aioqueue.h
#define MAX 10
typedef struct {
struct aiocb cb;
int fd;
int valid;
} aio_pack;
aio_pack aio_array[MAX];
void aio_add(struct aiocb a, int fd);
void aio_check();
The problem is that if i call aio_check after i added a task i always get the
At least one AIO task is in progress
message. Even if it's clear that the task has finished.
I suppose that it might be due to the fact that im passing a copy of the struct aiocb in a moment where the aio_error is EINPROGRESS and as its a copy it never gets updated. But im pretty lost at this moment. Any help would be greatly appreciated.
Thank you in advance.
You need to call aio_suspend() in order to process what i/o's have completed, otherwise aio_error() etc will never return differently. See https://github.com/ned14/llfio/blob/master/include/llfio/v2.0/detail/impl/posix/io_service.ipp#L290.
I'm new to pthread and multithreading, i have written a code like that.
#include <pthread.h>
#include <unistd.h>
void *nfc_read(void *arg)
{
int fd = -1;
int ret;
uint8_t read_data[24];
while(1){
ret = read_block(fd, 8, read_data);
if(!ret){
return (void)read_data;
}
}
}
int main(int argc, char *argv[])
{
pthread_t my_thread;
void *returnValue;
pthread_create(&my_thread, NULL, nfc_read, NULL);
pthread_join(my_thread, &returnValue);
printf("NFC card value is : %s \n", (char)returnValue);
printf("other process");
return 0;
}
Until the return value from nfc_read function, as I will have other code I need to run and I don't want to block in main. How can i do that?
This is a sample where a read thread runs concurrently to the "main" thread which is doing other work (in this case, printing dots and sleeping).
To keep things simple, a simulated the reading from an input device with copying a constant string character by character. I guess, this is reasonable as the synchronization of threads is focused.
For the synchronization of threads, I used atomic_bool with atomic_store() and atomic_load() which are provided by the Atomic Library (since C11).
My sample application test-concurrent-read.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
/* sampe input */
const char sampleInput[]
= "This is sample input which is consumed as if it was read from"
" a (very slow) external device.";
atomic_bool readDone = ATOMIC_VAR_INIT(0);
void* threadRead(void *pArg)
{
char **pPBuffer = (char**)pArg;
size_t len = 0, size = 0;
int c; const char *pRead;
for (pRead = sampleInput; (c = *pRead++) > 0; sleep(1)) {
if (len + 1 >= size) {
if (!(*pPBuffer = realloc(*pPBuffer, (size + 64) * sizeof(char)))) {
fprintf(stderr, "ERROR! Allocation failed!\n");
break;
}
size += 64;
}
(*pPBuffer)[len++] = c; (*pPBuffer)[len] = '\0';
}
atomic_store(&readDone, 1);
return NULL;
}
int main()
{
/* start thread to read concurrently */
printf("Starting thread...\n");
pthread_t idThreadRead; /* thread ID for read thread */
char *pBuffer = NULL; /* pointer to return buffer from thread */
if (pthread_create(&idThreadRead, NULL, &threadRead, &pBuffer)) {
fprintf(stderr, "ERROR: Failed to start read thread!\n");
return -1;
}
/* start main loop */
printf("Starting main loop...\n");
do {
putchar('.'); fflush(stdout);
sleep(1);
} while (!atomic_load(&readDone));
putchar('\n');
void *ret;
pthread_join(idThreadRead, &ret);
/* after sync */
printf("\nReceived: '%s'\n", pBuffer ? pBuffer : "<NULL>");
free(pBuffer);
/* done */
return 0;
}
Compiled and tested with gcc in cygwin on Windows 10 (64 bit):
$ gcc -std=c11 -pthread -o test-concurrent-read test-concurrent-read.c
$ ./test-concurrent-read
Starting thread...
Starting main loop...
.............................................................................................
Received: 'This is sample input which is consumed as if it was read from a (very slow) external device.'
$
I guess, it is worth to mention why there is no mutex guarding for pBuffer which is used in main() as well as in threadRead().
pBuffer is initialized in main() before pthread_create() is called.
While thread_read() is running, pBuffer is used by it exclusively (via its passed address in pPBuffer).
It is accessed in main() again but not before pthread_join() which grants that threadRead() has ended.
I tried to find a reference by google to confirm that this procedure is well-defined and reasonable. The best, I could find was SO: pthread_create(3) and memory synchronization guarantee in SMP architectures which cites The Open Group Base Specifications Issue 7 - 4.12 Memory Synchronization.
I'm running a RT program on BeagleBone Black with Xenomai and trying to figure how to monitor/understand context switches (I know the concept of context switches) so that I can determine when my program (in C using POSIX skin) switches from primary and secondary mode.
Here's the program main_posix.c
#ifndef __XENO_SIM__
#ifndef __KERNEL__
#include <stdio.h>
#define xnarch_printf printf
#endif
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <pthread.h>
#include <mqueue.h>
#else /* __XENO_SIM */
#include <posix/posix.h>
#endif /* __XENO_SIM */
void warn_upon_switch(){
printf("Switched to Secondary Mode \n");
}
void *threadFunc(void *arg)
{
char *str;
int i = 0;
struct timespec delay, sleep;
unsigned long over;
int ret;
str=(char*)arg;
printf("In thread \n");
sleep.tv_sec = 1;
sleep.tv_nsec = 0;
#ifdef __XENO__
ret = pthread_set_mode_np(0, 0x00040000);
printf("Warn Bit Ret %d\n", ret);
#endif /* __XENO__ */
// run this for some arbitrary time
while(i < 110000000 )
{
clock_nanosleep(CLOCK_REALTIME, 0, &sleep, NULL);
printf("threadFunc says: %s\n",str);
++i;
}
return NULL;
}
int main(void)
{
signal(SIGXCPU, warn_upon_switch);
signal(SIGKILL, warn_upon_switch);
pthread_t pth;
double i = 0;
int ret;
pthread_attr_t tattr;
struct sched_param sparam;
sparam.sched_priority = 99;
ret = pthread_attr_init(&tattr);
printf("Init Return Val %d\n", ret);
ret = pthread_setschedparam(pth,SCHED_FIFO, &sparam);
printf("SetSchedParam Ret Value %d\n", ret);
pthread_create(&pth,&tattr,threadFunc,"foo");
printf("main waiting for thread to terminate...\n");
pthread_join(pth,NULL);
return 0;
}
I'm also monitoring /proc/xenomai/stat continuously through watch
I see that CSWand MSW for PID 3323 changes continuously.
Here's the output of ps -e -o class,rtprio,pri,nice,cmd | grep ./main_posix
The output is as follows
My questions are as follows
How do I know if my program is running in primary or secondary mode?
I get the return value of ret = pthread_setschedparam(pth,SCHED_FIFO, &sparam); as 16 which is EBUSY. Any idea why?
Tried catching the switch signal using signal(SIGXCPU, warn_upon_switch);. The function never gets called.
If the program can be seen in Linux (meaning it gets a PID through the Linux kernel), does it mean its running in secondary mode?
In proc/xenomai/stat, I see two processes for the same program. Is it the main and the thread?
Here are some resources I used
Periodic thread fails real-time in Xenomai
Xenomai clock_nanosleep in POSIX skin jumps to Linux Kernel
http://xenomai.org/2014/08/porting-a-linux-application-to-xenomai-dual-kernel/#Using_the_PTHREAD_WARNSW_bit
http://www.xenomai.org/documentation/xenomai-2.6/html/api/sigxcpu_8c-example.html
I got stuck when I was trying to print the summary of all threads (namely, grand totals of a group of threads).
The C code below runs 10 threads, simulating agents that sell tickets. After running & completing the threads (i.e. after all the tickets are sold), I want to print the list of agents and corresponding number of tickets sold by that agent. However, the main process terminates as soon as it hits the line pthread_exit(NULL) (marked with a preceding comment) and the code does not return to main, where it is supposed to print the grand totals (this block is marked with a comment as well).
Can anyone tell what's wrong with the code?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
struct ThreadArgs {
int thNum;
int *numTickets;
int *soldTickets;
sem_t *lock;
};
void *SellTickets(void *th) {
struct ThreadArgs *thArgs;
int sleepTime;
thArgs = th;
while (1) {
sleepTime = rand();
if (sleepTime % 2) {
usleep(sleepTime % 1000000);
}
sem_wait(thArgs->lock);
if (*thArgs->numTickets == 0) {
break;
}
printf("There are %3d ticket(s). Agent %d sold a ticket.\n", *thArgs->numTickets, thArgs->thNum);
(*thArgs->numTickets)--;
sem_post(thArgs->lock);
(*thArgs->soldTickets)++;
}
sem_post(thArgs->lock);
pthread_exit(NULL);
}
void runThreads(int numAgents, int numTickets, int soldTickets[]) {
struct ThreadArgs thArgs[numAgents];
int agent;
pthread_t th[numAgents];
sem_t lock;
sem_init(&lock, 1, 1);
for (agent = 0; agent < numAgents; agent++) {
thArgs[agent].thNum = agent;
thArgs[agent].soldTickets = &soldTickets[agent];
thArgs[agent].numTickets = &numTickets;
thArgs[agent].lock = &lock;
pthread_create(&th[agent], NULL, SellTickets, &thArgs[agent]);
}
// when debugging, the process terminates here
pthread_exit(NULL);
}
int main() {
int agent, numAgents, numTickets, soldTickets[10];
numAgents = 10;
numTickets = 150;
for (agent = 0; agent < numAgents; agent++) {
soldTickets[agent] = 0;
}
runThreads(numAgents, numTickets, soldTickets);
// the process never executes the following block
for (agent = 0; agent < numAgents; agent++) {
printf("Agent %d sold %d ticket(s).\n", agent, soldTickets[agent]);
}
return 0;
}
pthread_exit() exits a thread, even the "main"-thread.
If main() ends all other thread go down as well.
As the "main"-thread is expected to do some final logging, it should wait until all threads spawned have ended.
To accomplish this in runThreads() replace the call to
pthread_exit(NULL);
by a loop calling pthread_join() for all PThread-IDs as returned by pthread_create().
Also you want to add error checking to all pthread*() calls, as you should do for every function call returning any relevant info, like for example indicating failure of the call.
I have a question I am writing a code that find the perfect number by brute forcing the algorithm which is required by my assignment. I want to see how far the ranges goes in 15 seconds. I tried using a while loop and an alarm but it seems to not work at all. How would I go from there?
Thanks
Heres my code:
#define _POSIX_SOURCE
#define _BSD_SOURCE
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
volatile int stop=0;
void sigalrm_handler( int sig ){
stop = 1;
}
int main(int argc, char **argv){
struct sigaction sact;
int num_sent = 0;
sigemptyset(&sact.sa_mask);
sact.sa_flags = 0;
sact.sa_handler = sigalrm_handler;
sigaction(SIGALRM, &sact, NULL);
alarm(15); /* Request SIGALRM in 60 seconds */
while (!stop) {
for (;;){
for (;;){
}
}
}
printf("%d \n", num_sent);
exit(0);
}
Even if the alarm gets triggered and set stop to a non-zero value you won't notice since your for loop doesn't return to the outer while. You need to apply the condition to all loops that should be stopped:
while (!stop) {
for (;!stop;){
for (;!stop;){
}
}
}
An alternative to alarm is simply checking whether you crossed a certain timepoint:
time_t end = time(0) + 15;
while (end < time(0)) {
for (;end < time(0);){
for (;end < time(0);){
}
}
}