I'm a newbie in error handling; in my code I need to test the returned value of a function and to print the error's description if an error happens.
In order to keep the code thread-safe I have to use strerror_r, but I have some difficult to use it. In the following code the error number 22 happens (ret_setschedparam is 22). How can I print the description of the error number 22, i.e. "Invalid argument", by using the strerror_r?
I think that this prototype should be the right strerror_r I need:
char *strerror_r(int errnum, char *buf, size_t buflen);
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <errno.h>
#include <string.h>
void *task();
int main()
{
pthread_attr_t attr;
struct sched_param prio;
pthread_t tid;
int ret_create;
int ret_setschedparam;
int ret_getschedparam;
int ret_join;
char *buf_setschedparam;
size_t size_setschedparam = 1024;
pthread_attr_init(&attr);
prio.sched_priority = 12;
ret_setschedparam = pthread_attr_setschedparam(&attr, &prio);
if (ret_setschedparam != 0) {
printf("Errore numero (pthread_attr_setschedparam): %s\n", strerror_r(errno, buf_setschedparam, size_setschedparam));
exit(EXIT_FAILURE);
}
ret_create = pthread_create(&tid, &attr, task, NULL);
printf("%d %d\n", ret_create, EPERM);
if (ret_create != 0) {
printf("Errore numero (pthread_create): %d\n", ret_create);
exit(EXIT_FAILURE);
}
ret_getschedparam = pthread_attr_getschedparam(&attr, &prio);
if (ret_getschedparam != 0) {
printf("Errore numero (pthread_attr_getschedparam): %d\n", ret_getschedparam);
exit(EXIT_FAILURE);
}
printf("Livello di priorità del thread: %d\n", prio.sched_priority);
ret_join = pthread_join(tid, NULL);
if (ret_join != 0) {
printf("Errore numero (pthread_join): %d\n", ret_join);
exit(EXIT_FAILURE);
}
return(0);
}
void *task()
{
printf("I am a simple thread.\n");
pthread_exit(NULL);
}
The compiler gives me an error: it said that the output of strerror_r is an int, not a char.
I think that this prototype should be the right strerro_r I need:
Note that this isn't the standard strerror_r interface, but a GNU extension.
You probably want to build your program with -D_GNU_SOURCE or add #define _GNU_SOURCE 1 to the top of your file to get this prototype instead of the standard one.
You are also not calling strerror_r correctly. This call:
char *buf_setschedparam;
size_t size_setschedparam = 1024;
... strerror_r(errno, buf_setschedparam, size_setschedparam)
promises to strerror_r that buf_setscheparam points to a buffer of size 1024. In fact that pointer is uninitialized, so once you get your program to build, it will promptly crash.
In addition, pthread_* functions do not set errno, they return the error code directly.
You want:
const size_t size_setschedparam = 1024;
char buf_setschedparam[size_setschedparam];
... sterror_r(ret_setschedparam, buf_setschedparam, size_setschedparam);
or even better:
char buf[1024];
... sterror_r(ret_setschedparam, buf, sizeof(buf));
Related
****** SOLVED ******
I wanted to copy multiple files using multi-threading. This ends in error: segmentation fault. Cannot figure out where.
What I tried: print("test"); on different lines, but gives me the same error. I think the main function is correct, something in the start_routine() block.
Code:
typedef struct filePair
{
char srcName[100];
char dstName[100];
} filePair;
void * start_routine(void *arg) //file handling using system calls
{
char tmp;
printf("Copying %s to %s.\n", ((filePair *)arg)->srcName, ((filePair *)arg)->dstName);
int src = open(((filePair *)arg)->srcName, O_RDWR); //open source file
if (!src)
{
printf("Cannot open source file.\n"); //error handling
exit(0);
}
//open dst file
int dst = open(((filePair *)arg)->dstName, O_WRONLY | O_CREAT, 0641);
if (!dst)
{
printf("Error in destination file.\n"); //error handling
exit(0);
}
while (read(src, &tmp, 1)) //while loop to copy contents
write(dst, &tmp, 1);
close(src); //close src and dst files
close(dst);
return NULL;
}
//main function...
The name of the type is struct filePair. A common way to make the usage of the type shorter is to incorporate a typedef:
typedef struct
{
char src[100];
char dst[100];
} filePair;
Then, you can refer to teh filePair type.
1.cause of segmentation fault in code is improper usage of pointers.
creating pointers of type filePair and not allocating sufficient memory for those pointers will cause segmentation fault. If we allocate sufficient memory for those pointers, it won't be a problem anymore.
prototype for pthread_create() is
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void
*(*start_routine) (void *), void *arg);
before passing *file1 in pthread_create() we should typecast file1 pointer to be of type
(void *).
Here I am providing a simple version without using pointers for filePair, but using filePair instances instead.
#include <stdio.h> /* printf, stderr */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* fork */
#include <stdlib.h> /* atoi */
#include <errno.h> /* errno */
#include <pthread.h> /* pthread */
#include <sys/stat.h>
#include <fcntl.h> /* file handling */
#include <time.h> /* CLOCK */
#include <string.h>
typedef struct
{
char srcName[100];
char dstName[100];
} filePair;
void * start_routine(void *arg) //file handling using system calls
{
char tmp;
printf("Copying %s to %s.\n", ((filePair *)arg)->srcName, ((filePair *)arg)->dstName);
int src = open(((filePair *)arg)->srcName, O_RDWR); //open source file
if (!src)
{
printf("Cannot open source file.\n"); //error handling
exit(0);
}
//open dst file
int dst = open(((filePair *)arg)->dstName, O_WRONLY | O_CREAT, 0641);
if (!dst)
{
printf("Error in destination file.\n"); //error handling
exit(0);
}
while (read(src, &tmp, 1)) //while loop to copy contents
write(dst, &tmp, 1);
close(src); //close src and dst files
close(dst);
return NULL;
}
/* main function */
int main(int argc, char *argv[])
{
pthread_t thread1; //Threads init
pthread_t thread2;
pthread_t thread3;
pthread_t thread4;
pthread_t thread5;
filePair file1;
strcpy(file1.srcName, "file1.dat");
strcpy(file1.dstName, "copy1.dat");
filePair file2;
strcpy(file2.srcName, "file2.dat");
strcpy(file2.dstName, "copy2.dat");
filePair file3;
strcpy(file3.srcName, "file3.dat");
strcpy(file3.dstName, "copy3.dat");
filePair file4;
strcpy(file4.srcName, "file4.dat");
strcpy(file4.dstName, "copy4.dat");
filePair file5;
strcpy(file5.srcName, "file5.dat");
strcpy(file5.dstName, "copy5.dat");
printf("\n Before threading.\n\n");
//Creating threads
pthread_create(&thread1, NULL, start_routine, (void *)&file1);
pthread_create(&thread2, NULL, start_routine, (void *)&file2);
pthread_create(&thread3, NULL, start_routine, (void *)&file3);
pthread_create(&thread4, NULL, start_routine, (void *)&file4);
pthread_create(&thread5, NULL, start_routine, (void *)&file5);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_join(thread3, NULL);
pthread_join(thread4, NULL);
pthread_join(thread5, NULL);
printf("\n After threading.\n\n");
return 0;
}
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 am trying to test out using papi, but I am getting some errors that I don't understand why they're occurring. I couldn't find anything online for them. The code is below
I am using PAPI and C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <memory.h>
#include <malloc.h>
#include "papi.h"
#define INDEX 100
static void test_fail(char *file, int line, char *call, int retval);
int main(int argc, char **argv) {
extern void dummy(void *);
float matrixa[INDEX][INDEX], matrixb[INDEX][INDEX], mresult[INDEX] [INDEX];
float real_time, proc_time, mflops;
long long flpins;
int retval, status = 0;
int i,j,k;
long_long values[1];
FILE *file;
file = fopen("output.txt","w");
retval = PAPI_library_init(PAPI_VER_CURRENT);
int EventSet = PAPI_NULL;
PAPI_create_eventset(&EventSet);
if(PAPI_add_event(EventSet, PAPI_LD_INS) != PAPI_OK)
{
fprintf(file,"PAPI failed to add Load/Store instructions\n");
}
if (PAPI_state(EventSet, &status) != PAPI_OK)
fprintf(file,"state fail\n");
fprintf(file, "State is now %d\n", status);
if (PAPI_start(EventSet) != PAPI_OK)
fprintf(file,"start fail\n");
if (PAPI_state(EventSet, &status) != PAPI_OK)
fprintf(file,"state2 fail\n");
fprintf(file, "State is now %d\n", status);
/* Initialize the Matrix arrays */
for ( i=0; i<INDEX; i++ ){
mresult[0][i] = 0.0;
matrixa[0][i] = matrixb[0][i] = rand()*(float)1.1; }
if((retval=PAPI_flops( &real_time, &proc_time, &flpins, &mflops))<PAPI_OK)
fprintf(file,"retval failed\n");
for (i=0;i<INDEX;i++)
{
for(j=0;j<INDEX;j++)
{
for(k=0;k<INDEX;k++)
{
mresult[i][j]=mresult[i][j] + matrixa[i][k]*matrixb[k][j];
}
}
}
if((retval=PAPI_flops( &real_time, &proc_time, &flpins, &mflops)) <PAPI_OK)
{
fprintf(infile,"ret2 failed\n");
}
fprintf(file,"Real_time:\t%f\nProc_time:\t%f\nTotal flpins:\t%lld \nMFLOPS:\t\t%f\n",
real_time, proc_time, flpins, mflops);
fflush(file);
fprintf(file,"%s\tPASSED\n", __FILE__);
fflush(file);
if (PAPI_read(EventSet, values) != PAPI_OK)
{fprintf(file,"read fail\n");}
if (PAPI_stop(EventSet, values) != PAPI_OK)
{fprintf(file,"stop fail\n");}
if (PAPI_cleanup_eventset(&EventSet) != PAPI_OK)
{fprintf(file,"cleanup fail\n");}
if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
{fprintf(file,"destroy fail\n");}
fprintf(file,"\nValues is %f\n", values[0]);
fflush(file);
fclose(file);
PAPI_shutdown();
exit(0);
}
In the output file, I just see the below:
State is now 1
State is now 2
retval failed
ret2 failed
Real_time: 0.000000
Proc_time: 0.000000
Total flpins: 99
MFLOPS: 0.000000
PAPI_flops.c PASSED
cleanup fail
destroy fail
I don't understand why ret, ret2, cleanup and destroy failed. Why?
You can use the PAPI_perror or PAPI_strerror functions to get the error message associated with an error return value. This may help track down why, for example, PAPI_flops is failing. (It could be that there is no support on your system for the required events.)
The reason why PAPI_cleanup_eventset is failing though is because it takes just the integer EventSet, not a pointer to it.
I'd strongly recommend emitting the error return value strings, and also compiling with warnings on — the latter would likely have found the issue with the wrong parameter type.
I have a piece of code to create function to print a message from input parameter.
I've been compiling the code with c9.io and works pretty well without warnings but when i do it locally it shows a warning like this:
child2bok: c39:11: warning: Ignoring return value of 'write', declares with attribute warn_unused_result [-Wunused -result]
And this is the code.Sure it is a problem with write() definition but i'm so novice with unix programming and no idea to solve it. It executes well but i'd like to remove the warning before i deliver to the teacher.
Here you are the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>
#include "rutines.h"
void children();
void show_help();
int main(int argc, char *argv[])
{
int ord;
if (argc > 1)
ord = atoi(argv[1]);
if (argc == 1)
{
show_help("Error");
exit(1);
}
children(ord);
}
void children(int ord)
{
char msg[10];
srand(getpid());
sleep(rand() % 5);
sprintf(msg, " %d", ord);
while (strlen(msg) > 0)
{
int written= write(1, msg, strlen(msg));
if (written < 0)
break;
exit(0);
}
void show_help(char *err_message)
{
write_string(err_message,"");
write_string("Usage: child2aok \n","");
}
You should check and handle the value returned by the write() command. From the write documentation:
write [...] may return less than count even under valid conditions.
Why don't you simply use printf(" %d", ord); instead of sprintf(msg, " %d", ord); write(1, msg, strlen(msg))?
write does not guarantee to write all the data; it may write as little as one byte (or block, or return an error, ...). So you have to use it in a loop:
bool write_all(int fd, void * buf, size_t len)
{
size_t remaining = len;
for (size_t n; (n = write(fd, buf, remaining)) > 0; remaining -= n)
{ }
return remaining == 0;
}
This function returns true if all bytes were written, and false on error.
I am testing kernel asynchronous io functions (not posix aio) and am trying to figure out how it works. The code below is a complete program where I simply write an array repeatedly to a file opened using O_DIRECT. I get an error in the callback function "write missed bytes expect 1024 got 0" (see the fprintf statement in work_done()).
For those not familiar with kernel aio, the code below does the following:
Init some structs
Prepare aio (io_prep_pwrite)
Submit io requests (io_submit)
Check for event completion (io_getevents)
Call a callback function to see if everything went ok.
I get an error at step 5. If I do not open the file using O_DIRECT, things work fine, but it beats the purpose of having async writes.
Can someone tell me what I am doing wrong? Is this the correct usage of kernel aio, for example, is my use of callbacks correct? Are there any restrictions on the usage of O_DIRECT?
I compile using 'gcc -Wall test.c -laio'
Thanks in advance.
/*
* File: myaiocp.c
* Author: kmehta
*
* Created on July 11, 2011, 12:50 PM
*
*
* Testing kernel aio.
* Program creates a 2D matrix and writes it multiple times to create a file of desired size.
* Writes are performed using kernel aio functions (io_prep_pwrite, io_submit, etc.)
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <omp.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <libaio.h>
char ** buf;
long seg_size;
int seg_rows;
double total_size;
char * filename;
static int wait_count = 0;
void io_task();
void cleanup();
void allocate_2D_matrix(int[]);
int file_open(char *);
void wr_done(io_context_t ctx, struct iocb* iocb, long res, long res2);
int main(int argc, char **argv) {
total_size = 1048576; //1MB
seg_size = 1024; //1kB
seg_rows = 1024;
filename = "aio.out";
int dims[] = {seg_rows, seg_size};
allocate_2D_matrix(dims); //Creates 2D matrix
io_task();
cleanup();
return 0;
}
/*
* Create a 2D matrix
*/
void allocate_2D_matrix(int dims[2]) {
int i;
char *data;
//create the matrix
data = (char *) calloc(1, dims[0] * dims[1] * sizeof (char));
if (data == NULL) {
printf("\nCould not allocate memory for matrix.\n");
exit(1);
}
buf = (char **) malloc(dims[0] * sizeof (char *));
if (buf == NULL) {
printf("\nCould not allocate memory for matrix.\n");
exit(1);
}
for (i = 0; i < dims[0]; i++) {
buf[i] = &(data[i * dims[1]]);
}
}
static void io_error(const char *func, int rc)
{
if (rc == -ENOSYS)
fprintf(stderr, "AIO not in this kernel\n");
else if (rc < 0)
fprintf(stderr, "%s: %s\n", func, strerror(-rc));
else
fprintf(stderr, "%s: error %d\n", func, rc);
exit(1);
}
/*
* Callback function
*/
static void work_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
if (res2 != 0) {
io_error("aio write", res2);
}
if (res != iocb->u.c.nbytes) {
fprintf(stderr, "write missed bytes expect %lu got %ld\n",
iocb->u.c.nbytes, res2);
exit(1);
}
wait_count --;
printf("%d ", wait_count);
}
/*
* Wait routine. Get events and call the callback function work_done()
*/
int io_wait_run(io_context_t ctx, long iter)
{
struct io_event events[iter];
struct io_event *ep;
int ret, n;
/*
* get up to aio_maxio events at a time.
*/
ret = n = io_getevents(ctx, iter, iter, events, NULL);
printf("got %d events\n", n);
/*
* Call the callback functions for each event.
*/
for (ep = events ; n-- > 0 ; ep++) {
io_callback_t cb = (io_callback_t)ep->data ; struct iocb *iocb = ep->obj ; cb(ctx, iocb, ep->res, ep->res2);
}
return ret;
}
void io_task() {
long offset = 0;
int bufIndex = 0;
//Open file
int fd = file_open(filename);
//Initialize structures
long i;
long iter = total_size / seg_size; //No. of iterations to reach desired file size (total_size)
io_context_t myctx;
if(0 != io_queue_init(iter, &myctx))
{
perror("Could not initialize io queue");
exit(EXIT_FAILURE);
}
struct iocb * ioq[iter];
//loop through iter times to reach desired file size
for (i = 0; i < iter; i++) {
struct iocb *io = (struct iocb*) malloc(sizeof (struct iocb));
io_prep_pwrite(io, fd, buf[bufIndex], seg_size, offset);
io_set_callback(io, work_done);
ioq[i] = io;
offset += seg_size;
bufIndex ++;
if (bufIndex > seg_rows - 1) //If entire matrix written, start again from index 0
bufIndex = 0;
}
printf("done preparing. Now submitting..\n");
if(iter != io_submit(myctx, iter, ioq))
{
perror("Failure on submit");
exit(EXIT_FAILURE);
}
printf("now awaiting completion..\n");
wait_count = iter;
int res;
while (wait_count) {
res = io_wait_run(myctx, iter);
if (res < 0)
io_error("io_wait_run", res);
}
close(fd);
}
void cleanup() {
free(buf[0]);
free(buf);
}
int file_open(char *filename) {
int fd;
if (-1 == (fd = open(filename, O_DIRECT | O_CREAT | O_WRONLY | O_TRUNC, 0666))) {
printf("\nError opening file. \n");
exit(-1);
}
return fd;
}
First of all, good job using libaio instead of POSIX aio.
Are there any restrictions on the usage of O_DIRECT ?
I'm not 100% sure this is the real problem, but O_DIRECT has some requirements (quoting mostly from TLPI):
The data buffer being transferred must be aligned on a memory boundary that is a multiple of the block size (use posix_memalign)
The file or device offset at which data transfer commences must be a multiple of the block size
The length of the data to be transferred must be a multiple of the block size
At a glance, I can see you are not taking aby precautions to align memory in allocate_2D_matrix.
If I do not open the file using O_DIRECT, things work fine, but it
beats the purpose of having async writes.
This happens not to be the case. Asynchronous I/O works well without O_DIRECT (for instance think of the number of system calls slashed).