8000 more specifically fwrite error handling and improvement for Fluent\Logger\FluentLogger::postImpl. · Issue #12 · fluent/fluent-logger-php · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

more specifically fwrite error handling and improvement for Fluent\Logger\FluentLogger::postImpl. #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
chobie opened this issue Feb 25, 2012 · 0 comments

Comments

@chobie
Copy link
Member
chobie commented Feb 25, 2012
  • fwrite returns:
FALSE => invalid parameters
integer => number of bytes written

why i misunderstood fwrite return null string. o.O

  • fwrite outputs errors:

only 1. we should catch this as PHP is able to change errors to exception.

php_sockop_write:
  php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %ld bytes failed with errno=%ld %s",(long)count, err, estr);
  • trace
fwrite -> php_stream_write -> _php_stream_write_buffer -> php_sockop_write

also i concerned about retry policy.

following lines are excerpted codes from PHP5_3.

/* {{{ proto int fwrite(resource fp, string str [, int length])
   Binary-safe file write */
PHPAPI PHP_FUNCTION(fwrite)
{
    zval *arg1;
    char *arg2;
    int arg2len;
    int ret;
    int num_bytes;
    long arg3 = 0;
    char *buffer = NULL;
    php_stream *stream;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &arg2, &arg2len, &arg3) == FAILURE) {
        RETURN_FALSE;
    }

    if (ZEND_NUM_ARGS() == 2) {
        num_bytes = arg2len;
    } else {
        num_bytes = MAX(0, MIN((int)arg3, arg2len));
    }

    if (!num_bytes) {
        RETURN_LONG(0);
    }

    PHP_STREAM_TO_ZVAL(stream, &arg1);

    if (PG(magic_quotes_runtime)) {
        buffer = estrndup(arg2, num_bytes);
        php_stripslashes(buffer, &num_bytes TSRMLS_CC);
    }

    ret = php_stream_write(stream, buffer ? buffer : arg2, num_bytes);
    if (buffer) {
        efree(buffer);
    }

    RETURN_LONG(ret);
}
/* }}} */

PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
{
    if (buf == NULL || count == 0 || stream->ops->write == NULL) {
        return 0;
    }

    if (stream->writefilters.head) {
        return _php_stream_write_filtered(stream, buf, count, PSFS_FLAG_NORMAL TSRMLS_CC);
    } else {
        return _php_stream_write_buffer(stream, buf, count TSRMLS_CC);
    }
}

/* Writes a buffer directly to a stream, using multiple of the chunk size */
static size_t _php_stream_write_buffer(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
{
    size_t didwrite = 0, towrite, justwrote;

    /* if we have a seekable stream we need to ensure that data is written at the
     * current stream->position. This means invalidating the read buffer and then
     * performing a low-level seek */
    if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0 && stream->readpos != stream->writepos) {
        stream->readpos = stream->writepos = 0;

        stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position TSRMLS_CC);
    }


    while (count > 0) {
        towrite = count;
        if (towrite > stream->chunk_size)
            towrite = stream->chunk_size;

        justwrote = stream->ops->write(stream, buf, towrite TSRMLS_CC);

        /* convert justwrote to an integer, since normally it is unsigned */
        if ((int)justwrote > 0) {
            buf += justwrote;
            count -= justwrote;
            didwrite += justwrote;

            /* Only screw with the buffer if we can seek, otherwise we lose data
             * buffered from fifos and sockets */
            if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
                stream->position += justwrote;
            }
        } else {
            break;
        }
    }
    return didwrite;

}


main/stream/xp_socket.c

php_sockop_write
/* {{{ Generic socket stream operations */
static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
{
    php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
    int didwrite;
    struct timeval *ptimeout;

    if (sock->socket == -1) {
        return 0;
    }

    if (sock->timeout.tv_sec == -1)
        ptimeout = NULL;
    else
        ptimeout = &sock->timeout;

retry:
    didwrite = send(sock->socket, buf, count, (sock->is_blocked && ptimeout) ? MSG_DONTWAIT : 0);

    if (didwrite <= 0) {
        long err = php_socket_errno();
        char *estr;

        if (sock->is_blocked && err == EWOULDBLOCK) {
            int retval;

            sock->timeout_event = 0;

            do {
                retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout);

                if (retval == 0) {
                    sock->timeout_event = 1;
                    break;
                }

                if (retval > 0) {
                    /* writable now; retry */
                    goto retry;
                }

                err = php_socket_errno();
            } while (err == EINTR);
        }
        estr = php_socket_strerror(err, NULL, 0);
        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "send of %ld bytes failed with errno=%ld %s",
                (long)count, err, estr);
        efree(estr);
    }

    if (didwrite > 0) {
        php_stream_notify_progress_increment(stream->context, didwrite, 0);
    }

    if (didwrite < 0) {
        didwrite = 0;
    }

    return didwrite;
}

#define php_stream_notify_progress_increment(context, dsofar, dmax) do { if ((context) && (context)->notifier && (context)->notifier->mask & PHP_STREAM_NOTIFIER_PROGRESS) { \
    (context)->notifier->progress += (dsofar); \
    (context)->notifier->progress_max += (dmax); \
    php_stream_notify_progress((context), (context)->notifier->progress, (context)->notifier->progress_max); } } while (0)

#define php_stream_notify_progress(context, bsofar, bmax) do { if ((context) && (context)->notifier) { \
    php_stream_notification_notify((context), PHP_STREAM_NOTIFY_PROGRESS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \
            NULL, 0, (bsofar), (bmax), NULL TSRMLS_CC); } } while(0)

PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity,
        char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC)
{
    if (context && context->notifier)
        context->notifier->func(context, notifycode, severity, xmsg, xcode, bytes_sofar, bytes_max, ptr TSRMLS_CC);
}
chobie added a commit that referenced this issue Feb 25, 2012
probably this will make fine.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant
0