I am working on a simple kernel module and I am taking arguments from command line. What I want to do is to check those arguments before loading the module.
I checked the argument and returned 1 to indicate the failure of init_module function so that the kernel module won't be loaded if arguments are not valid.
The problem was that the module was still loaded even if it didn't pass the argument check (took the first if statement). I typed sudo -f rmmod kernel_name, it complained the module is busy. How do I make it to load the module if it passes the argument check?
int init_module(){
//check argument here
if(failed){
//arguments are not valid. Return 1 to indicate the failure of init_module
return 1;
}
else{
register hook function here
return 0;
}
}
void cleanup_module(){
unregister hook here
}
I assume you are working on a Linux kernel module.
A positive return value still can be interpreted as success. A common practice is to return -error_code on error, -EINVAL in your case.
Related
So, I tried to find an answer to this question unsuccessfully.
I know what to do and how to manage such a case - by using fluss/NULL etc. afterward. But checking it is tricky to me.
So, basically:
open some file(successfully) - let's call the pointer: file.
after some code running...
fclose(file);
Now, how can I check after(before it's also an option) closing the file - that it really happened?
What is the condition? By demand, I need to handle this case by printing some specific errors.
You can use the following snippet:
#include <errno.h>
if(fclose(file) != 0)
{
fprintf(stderr, "Error closing file: %s", strerror(errno));
}
From the man pages, we see that an error in closing a file using fclose() sets the global variable errno to a value indicating what error occurred. The function strerror() takes this value of errno and outputs a string to help indicate what the error actually was.
Goal: allow c extension to receive block/proc for delayed execution while retaining current execution context.
I have a method in c (exposed to ruby) that accepts a callback (via VALUE hash argument) or a block.
// For brevity, lets assume m_CBYO is setup to make a CBYO module available to ruby
extern VALUE m_CBYO;
VALUE CBYO_add_callback(VALUE callback)
{
if (rb_block_given_p()) {
callback = rb_block_proc();
}
if (NIL_P(callback)) {
rb_raise(rb_eArgError, "either a block or callback proc is required");
}
// method is called here to add the callback proc to rb_callbacks
}
rb_define_module_function(m_CBYO, "add_callback", CBYO_add_callback, 1);
I have a struct I'm using to store these with some extra data:
struct rb_callback
{
VALUE rb_cb;
unsigned long long lastcall;
struct rb_callback *next;
};
static struct rb_callback *rb_callbacks = NULL;
When it comes time (triggered by an epoll), I iterate over the callbacks and execute each callback:
rb_funcall(cb->rb_cb, rb_intern("call"), 0);
When this happens I am seeing that it successfully executes the ruby code in the callback, however, it is escaping the current execution context.
Example:
# From ruby including the above extension
CBYO.add_callback do
puts "Hey now."
end
loop do
puts "Waiting for signal..."
sleep 1
end
When a signal is received (via epoll) I will see the following:
$> Waiting for signal...
$> Waiting for signal...
$> Hey now.
$> // process hangs
$> // Another signal occurs
$> [BUG] vm_call_cfunc - cfp consistency error
Sometimes, I can get more than one signal to process before the bug surfaces again.
I found the answer while investigating a similar issue.
As it turns out, I too was trying to use native thread signals (with pthread_create) which are not supported with MRI.
TLDR; the Ruby VM is not currently (at the time of writing) thread safe. Check out this nice write-up on Ruby Threading for a better overall understanding of how to work within these confines.
You can use Ruby's native_thread_create(rb_thread_t *th) which will use pthread_create behind the scenes. There are some drawbacks that you can read about in the documentation above the method definition. You can then run the callback with Ruby's rb_thread_call_with_gvl method. Also, I haven't done it here, but it might be a good idea to create a wrapper method so you can use rb_protect to handle exceptions the callback may raise (otherwise they will be swallowed by the VM).
VALUE execute_callback(VALUE callback)
{
return rb_funcall(callback, rb_intern("call"), 0);
}
// execute the callback when the thread receives signal
rb_thread_call_with_gvl(execute_callback, data->callback);
I am developing a shared-library L which is used by an other system service S. In my program I need to call a small program P, which uses Oracle shared libraries.
The small program P is packaged and installed correctly, and the environment variables, such as PATH,LD_LIBRARY_PATH and ORACLE_HOME are set correctly. I can run P on command line without any problem.
But when service S call my library L which runs the small program P via system(), it gives me a return code 127. I've googled, people says it's a command not found error, probably a PATH issue, so I've tried with absolute path like the following
int status = system("/usr/bin/myprog --args");
if (status < 0) { ... }
ret = WEXITSTATUS(status);
ret still equals 127.
Any idea please ? Thank you.
Update
It turns out that the service S is launched via command daemon, in its init.d script, I have found the following line:
daemon /usr/bin/myserv
if I export explicitly all my environment variables (PATH, ORACLE_HOME and LD_LIBRARY_PATH), it works. I don't know if daemon eliminates my environment variables.
this excerpt from the man page for system()
-----------------------------------------------------------------
The value returned is -1 on error (e.g., fork(2) failed), and the
return status of the command otherwise.
This latter return status is
in the format specified in wait(2).
Thus, the exit code of the command
will be WEXITSTATUS(status).
In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127)."
-----------------------------------------------------------------
indicates the 127 means that /bin/sh could not be executed.
Well, I have found the answer:How to make unix service see environment variables?,the environment variables are removed in init.d script.
I have a program called trickle that gives a warning and in its source code there is:
if (stat(sockname, &sb) == -1 &&
(errno == EACCES || errno == ENOENT))
warn("Could not reach trickled, working independently");
But the message I've got is:
trickle: Could not reach trickled, working independently: No such file or directory
Where does this No such file or directory come from?
I think that when you get a error value that is stocked in errno, the function warn can use it as a precision.
In this particular case I bet it's the ENOENT for Error NO ENTry that is in errno.
From man warn(3):
The err(), verr(), warn(), and vwarn() functions append an error message obtained from strerror(3) based on the global variable errno, preceded by another colon and space unless the fmt argument is NULL.
That message is coming from the second part of your if (..) comparison.
The code has executed a stat() system call, on sockname.
However, stat() returned ENOENT, which translates to "No such file or directory"
You need to find out how sockname is constructed to see whether it should have
been valid.
The error is coming from the stat function and is being reported as part of the warn function. In more detail, from the warn documentation:
The Fn err and Fn warn family of functions display a formatted error
message on the standard error output. In all cases, the last
component of the program name, a colon character, and a space are
output. If the Fa fmt argument is not NULL, the printf(3) -like
formatted error message is output. The output is terminated by a
newline character.
The Fn err , Fn verr , Fn warn , and Fn vwarn functions append an
error message obtained from strerror(3) based on a code or the global
variable errno preceded by another colon and space unless the Fa fmt
argument is NULL enter code here
So the "No such file or directory" is coming from the stat operation because it can't find sockname and is being passed to the warn function via a code.
I am using system function in C code to invoke cp command.
I want to know whether it got executed successfully or not?
Use system() function. It returns the status of command executed. If this is 0, then it would seem this is successfull.
Should be enought to check the return value of system call.
From man system on Mac:
The system() function returns the exit
status of the shell as returned by
waitpid(2), or -1 if an error occurred
when invoking fork(2) or waitpid(2). A return value of 127
means the execution of the shell
failed.