What would 3PC do in such a scenario? - distributed-transactions

We are using 3PC (three-phase commitment) for a distributed transaction. There are 4 nodes, A, B, C, D, where A is the coordinator.
A received OK from all others and sent the prepare-to-commit message to them.
While C and D received this message and moved to prepared state, B crashes and doesn't received this message (thus remaining in the wait state).
A timeouts on B and sends abort to all others, but only D receives the abort message, while C crashes before receiving the abort message.
Now the question is: What will C do after recovery? According to http://courses.cs.vt.edu/~cs5204/fall00/distributedDBMS/sreenu/3pc.html, C will commit upon recovery following the failure transition instead of aborting as D does. Won't that result in an inconsistent state? Or C has some mechanism to detect that the transaction in an aborted state?

I think there's a wrong assumption in your question about the behaviour of the B node? If B crashes before it moves to prepared state then it resides in waiting for state after the restart and will be aborted.
I expect that C node will be aborted as it will be commanded by the coordinator to do so. I think this will be similar to 2PC. It's up to coordinator to periodically check if the lost nodes are available again. When C is restarted the coordinator can see it and push the node to be rolled-back as abort message will be resent.

Related

Is it possible to send signals through IPC Message Passing Queue?

I have tried calling kill from process A to process B and the process B has successful reacted to the signal. The problem is I don't want to send signals from the kill function directly for two reasons:
1) Sometimes the process A may not have the permissions, ex. process B is ran by another user
2) I want to be able to send signals from A to B through the message queue
I am creating a message queue from which I send "objects" of the following structure
typedef struct msg {
long message_type;
char message_text[SIZE];
}message;
I want to know if it is possible for process A to signal B through IPC Message Passing. I know I can achieve this by sending the signal type into the message_text from process A to B and then inside the process B check the type of the signal and act properly but I was wondering if there is another way.
Would this be possible by passing sigaction objects as messages:
struct sigaction as;
//...
msgsnd(queue_id, &as, length, IPC_NOWAIT);
//...
I know this is completely infeasible but this is what I am trying to achieve. Thank you
Based upon your comments it seems that you want B to be able to receive messages but when it receives a "signal" message it needs to act like it received a regular signal. You mentioned that the B needed to react to SIGTERM or SIGINT from the "signal" message.
The way to achieve this is depends upon using POSIX message queues or System V message queues.
Either way it doesn't seem that you want to use polling of the message queue by the main thread of B as that would add to much latency to responding to the "signal" message.
So with POSIX message queues you can use mq_notify() to run either a thread or raise a signal that a new message has arrived. Otherwise B can use a thread (or even fork()) to poll the message queue.
After a "signal" message is received you have a couple of options. A) You can use either kill or raise in B to send a signal of the correct type to itself (or parent in case of fork), or B) just call a function that does what you want (that sort of thing).
Process A can send a "signal" message whenever it wants. But you need to understand that if you are using named queues they are persistent. That is that A can send a "signal" message before B even starts, and then when B starts that message is waiting there. Depending on how the message queue is made it can be N messages deep and have older messages in the queue. One way to deal with that is for B to empty the queue before processing any of the messages.
Message queues can’t achieve how signals do. With signal it is possible to asynchronously interrupt or kill process but with message queue when receiving process checks message or wait on it and exits after receiving message, it actually will ignore that message rest of path of execution(synchronous). But, It is possible to achieve with threads.
If you were using a POSIX message queues (using mq_send/mq_receive), then process B can request (with mq_notify) to be sent a signal every time a message is sent to the message queue. However, your example seems to be using a SYSV legacy message queue (msgsnd) which does not suppport any kind of notify.

Trying to understand deadlocks in c

I'm studying for my systems programming examination, but am having some trouble coming up with a simple deadlock example in c. I understand deadlocks occur whenever the waiting process is still holding on to another resource that the first needs, however I am having a difficult time understanding it in terms of c code. Are there any simple examples someone can provide?
Are there any simple examples someone can provide?
Here is a simple example: a piece of code might need to acquire two locks, A and B, e.g. so it can atomically modify two pieces of data, one protected by A and the other by B. For example:
pthread_mutex_t a, b;
pthread_mutex_lock(&a);
pthread_mutex_lock(&b);
// ... process data protected by A and B
pthread_mutex_unlock(&b);
pthread_mutex_unlock(&a);
At the same time, another piece of code can have the same requirement, but merely acquire the locks in the opposite order:
pthread_mutex_lock(&b);
pthread_mutex_lock(&a);
// ... process data protected by A and B
pthread_mutex_unlock(&a);
pthread_mutex_unlock(&b);
In isolation, either approach works just fine. But when the two pieces of code execute concurrently, the following can occur:
// neither lock is held
// thread 1 // thread 2
pthread_mutex_lock(&a); pthread_mutex_lock(&b);
// thread 1 now holds A // thread 2 now holds B
// thread 1 is waiting for B // thread 2 is waiting for A
pthread_mutex_lock(&b); pthread_mutex_lock(&a);
The last line constitutes a deadlock: thread 1 is blocked waiting for lock B, which is held by thread 2. Thread 2 is blocked waiting for lock A, which is held by thread 1. As written, the threads are blocked indefinitely and neither can proceed.

Multiple messages in message queue

This is probably a really dumb question, but googling isn't working out so here goes. I am writing a program using message queues to send a range of values to different processes. I have done research that indicates that I use msgsnd() to store a message on the queue and msgrcv() to receive messages. I need to store a start number and an end number in the queue. So my question is can I store multiple messages in this queue and if so, how to I go about storing them and retrieving them? TIA for all your help.
The concept of a queue means you can put things in (msgsnd) which creates one message in the queue. To receive one message, you have to call msgrcv. Each receive will normally only return one message, so if you send n messages, you have to receive n messages.
Queues are generally seen as FIFO (first in, first out), so the message creates by the first msgsnd will be the first message returned by msgrcv.
This is a little weakend if you message queues that operate over the network (and/or in a cluster). Due to network latency/failover/retries etc messages can get out of order, so it's generally advised to build the messages with all necessary information in them to process correctly for those cases.

What happens when I MPI_Send to a process that has finished?

What happens when I MPI_Send to a process that has finished?
I am learning MPI, and writing a small sugar distribution-simulation in C. When the factories stop producing, those processes end. When warehouses run empty, they end. Can I somehow tell if the shop's order to a warehouse did not succeed(because the warehouse process has ended) by looking at the return value of MPI_Send? The documentation doesn't mention a specific error code for this situation, but that no error is returned for success.
Can I do:
if (MPI_Send(...)) {
...
/* destination has ended */
...
}
And disregard the error code?
Thanks
Writing code with unmatched MPI_Send calls is not allowed by the standard. Among other things, this means the resulting behavior will be implementation dependent. The range of possible behaviors includes several "obvious" options: exit, hang/deadlock, memory corruption, and so on.
Most implementations have some level of debugging output that could be helpful in tracking down this kind of logical programing error. It is possible to use MPI_Wait* to barrier on the completion of all MPI_Send/MPI_Recv pairs. In a general case, it is not possible to know that the MPI_Send will not be matched until the recv'ing node enters MPI_Finalize. Said another way, a use of a barrier in this condition will cause the program to hang.
In any event, this would be an error condition for MPI_Finalize. The target rank for the MPI_Send should be detected as having exited...so that the MPI_Send can never be matched. However, this kind of error condition may cause the MPI job to fail to clean up all the rank processes.
As far as I'm aware, the MPI standard defines no return value and no out parameters for MPI_Send(): it doesn't provide any information on the message sending event, probably because message buffering can make it so that no information is available on the result at the time the call returns.
If you want one process to see when another ends, you should send a message from the finishing process with a designated tag, and peridocally post nonblocking receives at the other process to see if an exit notification was sent.
Or, if you want the entire program to abort when one process stops, the easiest thing to do is to simply call MPI_Abort() in the finishing process with MPI_COMM_WORLD as the communicator, which is guaranteed to shut down all processes.
Edit: To actually answer the question in the title, "What happens when I MPI_Send to a process that has finished?": as I understand it, that depends on whether buffering is used or not. If buffering is not used, then the program will hang. If buffering is used, then MPI_Send() will buffer the message and the process will continue to run, but because no matching receive will ever be posted, the message will never leave the buffer. Doing this a lot will eventually cause the program to run out of memory.

dbus: flush connection?

When I do a "dbus_connection_close", do I need to flush the message queue?
In other words, do I need to continue with "dbus_connection_read_write_dispatch" until I receive the "disconnected" indication or is it safe to stop dispatching?
Updated: I need to close the connection to DBus in a clean manner. From reading the documentation, all the clean-up must be done prior to "unreferencing" the connection and this process isn't very well documented IMO.
After some more digging, it appears that there are two types of connection: shared and private.
The shared connection mustn't be closed just unreferenced. Furthermore, it does not appear that the connection must be flushed & dispatched unless the outgoing messages must be delivered.
In my case, I just needed to end the communication over DBus as soon as possible without trying to salvage any outgoing messages.
Thus the short answer is: NO - no flushing / no dispatching needs to be done prior to dbus_connection_unref.
Looking at the documentation for dbus_connection_close(), the only thing that may be invoked is the dispatch status function to indicate that the connection has been closed.
So, ordering here is something you probably want to pay attention to .. i.e getting notified of a closed / dropped connection prior to things left in the message queue.
Looking at the source of the function, it looks like the only thing its going to do is return if fail, i.e. invalid connection / NULL pointer. Otherwise, it (seems) to just hang up.
This means yes, you probably should flush the message queue prior to hanging up.
Disclaimer: I've only had to talk to dbus a few times, I'm not by any means an authority on it.

Resources