Home > OS >  Void function required to return value?
Void function required to return value?

Time:02-10

I wrote a function as follows which is used to create pthread:

void *downloadfile(void *arg)
{
  char *req_path = NULL;
  char local_path[PATH_BUFFER_SIZE];
  int returncode = 0;
  gfcrequest_t *gfr = NULL;
  FILE *file = NULL;
  int i = 0;
  
  /* Build your queue of requests here */
  for (i = 0; i < nrequests; i  ) {
    // pthread mutex locking
    // doing something
    // pthread mutex unlocking

    localPath(req_path, local_path);

    file = openFile(local_path);

    gfr = gfc_create();
    gfc_set_server(&gfr, server);
    gfc_set_path(&gfr, req_path);
    gfc_set_port(&gfr, port);
    gfc_set_writefunc(&gfr, writecb);
    gfc_set_writearg(&gfr, file);

    fprintf(stdout, "Requesting %s%s\n", server, req_path);

    if (0 > (returncode = gfc_perform(&gfr))) {
      fprintf(stdout, "gfc_perform returned an error %d\n", returncode);
      fclose(file);
      if (0 > unlink(local_path))
        fprintf(stderr, "warning: unlink failed on %s\n", local_path);
    } else {
      fclose(file);
    }

    if (gfc_get_status(&gfr) != GF_OK) {
      if (0 > unlink(local_path))
        fprintf(stderr, "warning: unlink failed on %s\n", local_path);
    }

    fprintf(stdout, "Status: %s\n", gfc_strstatus(gfc_get_status(&gfr)));
    fprintf(stdout, "Received %zu of %zu bytes\n", gfc_get_bytesreceived(&gfr),
            gfc_get_filelen(&gfr));

    gfc_cleanup(&gfr);
    req_path = NULL;
  }
//  return 0;
}

I commented out the "return 0;" statement because this is a void function thus should not return any value. But the compiler complains that

error: control reaches end of non-void function

If I uncomment the "return 0;" statement, the error goes away. I am so puzzled. How can the compiler require a void function to return value? Could somebody please help out?

CodePudding user response:

From your description I assume that your function downloadfile is to be used as function-pointer argument in a pthread_create call.

So you have a basic misunderstanding. The function pointer used for pthread_create is not a function pointer to a "void function". It's a function pointer to a function that returns a void pointer. (BTW: You can get the return value using the pthread_join function if needed)

So in other other words: Your function must return a void-pointer. If you have nothing meaningful to return just use return NULL;

Extra details:

From https://man7.org/linux/man-pages/man3/pthread_create.3.html we have:

   int pthread_create(pthread_t *restrict thread,
                      const pthread_attr_t *restrict attr,
                      void *(*start_routine)(void *),
                      void *restrict arg);

The interresting part here is void *(*start_routine)(void *) which means:

 void *(*start_routine)(void *)
 \----/\--------------/\------/
    |   Function ptr       |
    |   to a function   /----------\   
    |        that takes void pointer as argument
    |   and returns
/----------\
void pointer 

So again - to use a correct function pointer argument for pthread_create you need a function that returns a void-pointer.

CodePudding user response:

because this is a void function

No it isn't. It is a function returning a void*. Pthreads only work with functions of the signature void* f (void*). That's the only kind of function you can use, as per pthread library design. You don't get to chose anything else.

error: control reaches end of non-void function

This is a nice error to get since your code without the return statement contains undefined behavior. Specifically C17 6.9.1/12 says:

If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

As in, if you didn't use return and the caller checks the result - which will happen here inside the pthreads lib, then anything can happen. It is a bug.

If you aren't interested in returning anything from the function, you must return NULL; or the equivalent return 0;.

Notably, the difference between returning void and void* is fundamental C - it is something you should have studied at a much earlier stage before moving on to multi-threading, which is a more advanced topic.

  • Related