View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0003107 | libmicrohttpd | external API | public | 2013-11-10 19:58 | 2013-11-17 12:37 |
| Reporter | pwielders | Assigned To | Christian Grothoff | ||
| Priority | normal | Severity | major | Reproducibility | always |
| Status | closed | Resolution | won't fix | ||
| Platform | X86 | OS | Linux | OS Version | Ubuntu 13.04 |
| Summary | 0003107: ContentReaderFreeCallback not called in case the "reference" to the response object is maintained. | ||||
| Description | Whenever the Response object is maintained to use for several responses, the ContenteReaderFreeCallback is not called in case the ContentReaderCallback reports an END of the stream. This makes the concept of maintaining the Response object for handling multiple objects useless. | ||||
| Steps To Reproduce | Building a C++ wrapper around the C calls: void SendResponse (struct MHD_Connection *connection) { ASSERT (_state != QUEUED); if (_state != HANDLED) // So, IDLE or LOADED { // Send the default answer!!!! if (_XML == true) { _responseText = "<html><head><title>Error</title></head><body>Bad data</body></html>"; } else { _responseText = "<html><head><title>Error</title></head><body>Bad data</body></html>"; } _status = HTTP_FAIL; } _processed = 0; _state = QUEUED; struct MHD_Response* response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, _recommendedBlockSize, &ContentReaderCallback, this, &ContentReaderFreeCallback); MHD_add_response_header(response, "Content-Type", "text"); MHD_queue_response (connection, _status, response); MHD_destroy_response (response); } static long int ContentReaderCallback (void *cls, uint64_t pos, char *buf, size_t max) { ASSERT (static_cast<Request*>(cls)->_state == QUEUED); const string& myBuffer = (static_cast<Request*>(cls))->_responseText; size_t length = myBuffer.length() - pos; if (length > max) { length = max; } const char* source = &(myBuffer.data()[pos]); std::cout << "Transfer: " << length << " bytes." << std::endl; ::memcpy (buf, source, length); return (length == 0 ? MHD_CONTENT_READER_END_OF_STREAM : length); } static void ContentReaderFreeCallback (void* cls) { std::cout << "Completed !!" << std::endl; static_cast<Request*>(cls)->_state = IDLE; } The code above works fine as the Creation of the response object id one prior to the enqueu and released (destroyed) after the enqueu. If, however, this creation of the response object is moved to the constructur of the Request class and cleared in the destructor of the request class, the ContentReaderFreeCallback is never called. | ||||
| Additional Information | Full source code, for C++ wrapper attached. Still in experimental phase, needs to be restructures | ||||
| Tags | No tags attached. | ||||
| Attached Files | |||||
|
|
This is totally intentional and expected behavior: the free callback is used to allow applications to clean up after themselves, it has nothing to do with an individual client reaching the end of the stream. If you do keep a reference to the response, you are telling MHD that you might pass the same response object for another request, and thus MHD will not invoke the cleaner callback. Just to be clear, "free" is used to _close_ the file. If you use the same response object with multiple requests, there is NO guarantee that they will access it sequentially and so you could not use the 'clenaer' to reset the stream either. MHD might ask the response to deliver bytes 0-5, then 6-10, then AGAIN 0-5, then 11-20 and then 6-EOF and then 21-EOF. If your response object is shared with multiple connection, that is a legitimate request sequence that it must be able to handle. Thus, having a callback to the cleaner after "EOF" is useless anyway. Not to mention that if there is something you really need to do upon reaching EOF, you can simply do that within your callback at that time. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2013-11-10 19:58 | pwielders | New Issue | |
| 2013-11-10 19:58 | pwielders | File Added: restserver2.cpp | |
| 2013-11-17 12:37 | Christian Grothoff | Note Added: 0007645 | |
| 2013-11-17 12:37 | Christian Grothoff | Assigned To | => Christian Grothoff |
| 2013-11-17 12:37 | Christian Grothoff | Status | new => assigned |
| 2013-11-17 12:37 | Christian Grothoff | Status | assigned => closed |
| 2013-11-17 12:37 | Christian Grothoff | Resolution | open => won't fix |
| 2024-01-21 13:24 | Christian Grothoff | Category | libmicrohttpd API => external API |